diff --git a/_snippets/javascript--api--near.mdx b/_snippets/javascript--api--near.mdx index 4148ae4..854a138 100644 --- a/_snippets/javascript--api--near.mdx +++ b/_snippets/javascript--api--near.mdx @@ -1,5 +1,5 @@ - The `near` API allows you to interact with the Rownd's [NEAR integration](../configuration/web3/near-overview.mdx). + The `near` API allows you to interact with the Rownd's [NEAR integration](/configuration/web3/near-overview). Creates an implicit NEAR account for the current user if one doesn't already exist diff --git a/configuration/authentication-methods/overview.mdx b/configuration/authentication-methods/overview.mdx index 9ee879a..9397e0c 100644 --- a/configuration/authentication-methods/overview.mdx +++ b/configuration/authentication-methods/overview.mdx @@ -89,7 +89,7 @@ Rownd's adaptive sign-in can detect the user's device and adjust the available a ### Customizing sign in methods by device on the Rownd platform 1. **Navigate to the Sign in methods tab:** After installing Rownd with a code snippet or SDK, navigate to the sign in methods tab in the Rownd Platform. ![Check out the sign in methods tab.](/images/Sign-in-methods-page.png) -2. **Configure [mobile app settings](configuration/mobile.mdx):** If you have a mobile app, configure your Google, Apple and mobile settings to get started. This will ensure proper deep linking to your mobile apps with your new customizations. +2. **Configure [mobile app settings](/configuration/mobile/overview):** If you have a mobile app, configure your Google, Apple and mobile settings to get started. This will ensure proper deep linking to your mobile apps with your new customizations. ![Configure mobile app settings](/images/Mobile-app-settings2.png) 3. **Customize sign in method orders by device:** Select the device type at the top (Desktop, iOS, Android), drag, drop, prioritize, and hide methods until you’re liking your customizations for each device type. We recommend prioritizing Apple sign in on iOS devices and prioritizing Google sign in on Android devices. ![Customize the order and visability by device.](/images/iOS-customize-sign-in-method.png) diff --git a/configuration/customizations/global-style.mdx b/configuration/customizations/global-style.mdx index e204737..48858a6 100644 --- a/configuration/customizations/global-style.mdx +++ b/configuration/customizations/global-style.mdx @@ -39,13 +39,13 @@ Rownd offers a range of style customizations to best match your brand look and f Global styles will span across all Rownd UI elements, but you have additional customization options for the content and appearances of Rownd emails, modals, and screens. -- **[Email customizations](configuration/customizations/email-customization.mdx).** Customize the language and logo that appear in user verification emails for email sign in. +- **[Email customizations](/configuration/customizations/email-customization).** Customize the language and logo that appear in user verification emails for email sign in. - **Sign in modal.** From the "Modals" tab, you can update the content, visuals, and links on your Rownd sign in modal. - **Verification modal.** From the "Modals" tab, you can update the content and visuals on your Rownd verification modal. -- **App download screen.** From the "Emails and screens" tab, you can update the content and visuals on the Rownd App download screen. This screen appears if your user is attempting mobile app sign in and does not yet have the app on their device. Be sure to configure your [mobile app settings](configuration/mobile.mdx) for this to work properly. +- **App download screen.** From the "Emails and screens" tab, you can update the content and visuals on the Rownd App download screen. This screen appears if your user is attempting mobile app sign in and does not yet have the app on their device. Be sure to configure your [mobile app settings](/configuration/mobile/overview) for this to work properly.
diff --git a/migration/cognito.mdx b/migration/cognito.mdx index 75d9059..4781cb4 100644 --- a/migration/cognito.mdx +++ b/migration/cognito.mdx @@ -19,7 +19,7 @@ Here's what you'll work through as part of this migration: ## Update back-end code You'll need to update your backend APIs to accept Rownd-signed JWTs instead of AWS Cognito JWTs. - 1. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend). + 1. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend/overview). 2. Locate code that uses the AWS Cognito to manage users, validate tokens, and so on. Remove this code. Our SDKs provide functions to validate Rownd tokens, fetch user data, and in some cases middleware that you can plug directly into your request handlers to authenticate users automatically. diff --git a/migration/firebase.mdx b/migration/firebase.mdx index d302c74..f8078b0 100644 --- a/migration/firebase.mdx +++ b/migration/firebase.mdx @@ -26,7 +26,7 @@ Some Firebase apps don't have a back-end component. If that's the case for you, In most cases, you should be able to remove all Firebase Authentication-related code from any backend servers or functions you're using. Take the following steps to migrate your back-end from Firebase Authentication to Rownd. 1. If you're only using Firebase Authentication, uninstall Firebase SDKs from your back-end project. -2. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend). +2. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend/overview). 2. Locate code that uses the Firebase SDK to manage users, validate tokens, and so on. Remove this code. 3. Replace the previous Firebase code with Rownd code. See our [GitHub repo](https://github.com/rownd/migration-firebase) for an example of this code migration. @@ -36,7 +36,7 @@ Firebase provides a limited amount of pre-built UI, so it's likely you've create If you plan to keep existing users signed-in (and you should!), keep your Firebase SDKs installed until you've migrated all of your active users to Rownd. This usually takes a month or two depending on your users' behavior patterns. 1. Remove existing authentication code, authentication screens, and so on. (If you're migrating a mobile app, you may want to keep the splash screen, although Rownd can help you let users into your app before they fully authenticate). -2. Install a [front-end web SDK](/sdk-reference/web) or [mobile SDK](/sdk-reference/mobile) for your platform or framework. +2. Install a [front-end web SDK](/sdk-reference/web/overview) or [mobile SDK](/sdk-reference/mobile/overview) for your platform or framework. 3. Add the required bits of Rownd code to authenticate users and protect your front-end. Here's an example where we'll update the front-end and replace Firebase authentication with Rownd. React code examples are provided for demonstration purposes. diff --git a/rownd-docusaurus/.gitignore b/rownd-docusaurus/.gitignore new file mode 100644 index 0000000..b2d6de3 --- /dev/null +++ b/rownd-docusaurus/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/rownd-docusaurus/README.md b/rownd-docusaurus/README.md new file mode 100644 index 0000000..b28211a --- /dev/null +++ b/rownd-docusaurus/README.md @@ -0,0 +1,41 @@ +# Website + +This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. + +## Installation + +```bash +yarn +``` + +## Local Development + +```bash +yarn start +``` + +This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. + +## Build + +```bash +yarn build +``` + +This command generates static content into the `build` directory and can be served using any static contents hosting service. + +## Deployment + +Using SSH: + +```bash +USE_SSH=true yarn deploy +``` + +Not using SSH: + +```bash +GIT_USER= yarn deploy +``` + +If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. diff --git a/rownd-docusaurus/api-reference/authentication/create-magic-link.mdx b/rownd-docusaurus/api-reference/authentication/create-magic-link.mdx new file mode 100644 index 0000000..c4e5fe5 --- /dev/null +++ b/rownd-docusaurus/api-reference/authentication/create-magic-link.mdx @@ -0,0 +1,64 @@ +--- +title: "Create a magic link" +openapi: "POST /hub/auth/magic" +--- + +Generate a magic link for user authentication or as a short link. + + + +### Request + +Headers: + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +Body (JSON): + +```json +{ + "purpose": "auth", + "redirect_url": "/somewhere/in/my/app", + "expiration": "30d", + "link_data": {"utm": "newsletter"}, + "verification_type": "email", + "data": {"email": "user@example.com"} +} +``` + +### Try it + +```bash title="cURL" +curl --request POST \ + --url https://api.rownd.io/hub/auth/magic \ + --header 'X-Rownd-App-Key: ' \ + --header 'X-Rownd-App-Secret: ' \ + --header 'Content-Type: application/json' \ + --data '{ + "purpose": "auth", + "redirect_url": "/somewhere/in/my/app", + "expiration": "30d", + "link_data": {"utm": "newsletter"}, + "verification_type": "email", + "data": {"email": "user@example.com"} + }' +``` + +### Response + +200 - application/json + +```json title="200 OK" +{ + "link": "https://rownd.link/abc123", + "link_meta": { + "purpose": "auth", + "redirect_url": "/somewhere/in/my/app" + } +} +``` + + +Links created with purpose `auth` should only be sent to a single user. Use `shorten` for broadcast links. + diff --git a/rownd-docusaurus/api-reference/authentication/overview.mdx b/rownd-docusaurus/api-reference/authentication/overview.mdx new file mode 100644 index 0000000..19ebdee --- /dev/null +++ b/rownd-docusaurus/api-reference/authentication/overview.mdx @@ -0,0 +1,38 @@ +--- +title: "Authentication Overview" +sidebarTitle: Overview +--- + +Rownd's API leverages two authentication mechanisms depending on which operation you're invoking. **User-scoped** APIs enable your users to manage their profile information, register passkeys, set preferences, and so on. **App-scoped** APIs allow you to manage aspects of your app, read and update user profiles, add or remove users, and fetch keys necessary for validating a user's bearer token. + +Rownd leverages API keys for app-scoped authentication. You'll see these referred to as "app keys" throughout the platform and documentation. + +To generate a new app key/secret pair, see this [reference guide](/configuration/app-credentials). + +### App-scoped authentication + +When making calls to the Rownd REST API, you must include your app key/secret pair in the request headers. The app key is used to identify the app making the request, and the secret is used to authenticate the request. + +Ensure the following headers are present: + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + + +User-initiated requests leverage bearer token authentication, which is generated when a user signs in. You'll usually leverage this token from one of our SDKs in order to call user-based Rownd APIs in addition to your own API stack. + + +### User-scoped authentication + +In most cases, Rownd's SDKs and the Rownd Hub call Rownd APIs on behalf of a user. In these cases, the user's bearer token is included in the request headers. The bearer token is used to identify the user making the request, and to authenticate the request. + +We recommend that you use Rownd bearer tokens to authenticate users against your own API or service. Since Rownd's tokens are signed asymmetrically, you can use our public JWK set to validate a token's signature. + + +If you're using a Rownd server SDK (e.g., Node.js), convenience methods or middleware are provided to automatically validate a bearer token and attach the user's profile to the request object. + + +Use these endpoints to fetch our OIDC and/or JWK configurations: + +- [OIDC configuration](/api-reference/authentication/retrieve-oidc) +- [JWK set](/api-reference/authentication/retrieve-jwk) diff --git a/rownd-docusaurus/api-reference/authentication/retrieve-jwk.mdx b/rownd-docusaurus/api-reference/authentication/retrieve-jwk.mdx new file mode 100644 index 0000000..643300f --- /dev/null +++ b/rownd-docusaurus/api-reference/authentication/retrieve-jwk.mdx @@ -0,0 +1,38 @@ +--- +title: "Retrieve Rownd JWK set" +openapi: "GET /hub/auth/keys" +--- + +Retrieve the current JWK set that validates Rownd-issued tokens. + + + +### Try it + +```bash title="cURL" +curl --request GET \ + --url https://api.rownd.io/hub/auth/keys +``` + +### Response + +200 - application/json — Keys retrieved successfully + +```json title="200 OK" +{ + "keys": [ + { + "kty": "OKP", + "alg": "EdDSA", + "kid": "sig-1644937360", + "use": "sig", + "crv": "Ed25519", + "x": "ChrFqbu1T7TTuLFg3o_coBNwqdm_O5Llok1dey0G2Tg" + } + ] +} +``` + + +Use these keys to validate Rownd JWTs in your backend. Keys may rotate; always fetch the current set. + diff --git a/rownd-docusaurus/api-reference/authentication/retrieve-oidc.mdx b/rownd-docusaurus/api-reference/authentication/retrieve-oidc.mdx new file mode 100644 index 0000000..cf9ed0c --- /dev/null +++ b/rownd-docusaurus/api-reference/authentication/retrieve-oidc.mdx @@ -0,0 +1,33 @@ +--- +title: "Retrieve OIDC configuration" +openapi: "GET /hub/auth/.well-known/oauth-authorization-server" +--- + +Retrieve Rownd's OAuth 2.0/OIDC metadata document. + + + +### Try it + +```bash title="cURL" +curl --request GET \ + --url https://api.rownd.io/hub/auth/.well-known/oauth-authorization-server +``` + +### Response + +200 - application/json — OIDC configuration + +```json title="200 OK" +{ + "issuer": "https://api.rownd.io/hub/auth", + "authorization_endpoint": "https://api.rownd.io/hub/auth/authorize", + "token_endpoint": "https://api.rownd.io/hub/auth/token", + "jwks_uri": "https://api.rownd.io/hub/auth/keys" + // ... properties omitted +} +``` + + +Use this document to dynamically configure OpenID Connect clients and discover Rownd endpoints. + diff --git a/rownd-docusaurus/api-reference/groups/overview.mdx b/rownd-docusaurus/api-reference/groups/overview.mdx new file mode 100644 index 0000000..a197cb0 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/overview.mdx @@ -0,0 +1,68 @@ +--- +title: Groups overview +sidebarTitle: Overview +description: Groups API documentation +--- + +With Rownd groups, you can segment your application users into logical segments. Each segment contains group members +which are tied back to application users via their `user_id`. With the group APIs, you can add a group member +directly or by creating a group invite. Group invites result in a one-time-use link that you can send to a +user that when visited adds them to the group with specific roles. Each group member is assigned to roles, +which are an array of strings like `"admin"` or `"editor"`. You can specify member roles via member creation +or updates, or during an invite creation. + +The groups APIs are split into two sets that differ slighly on imlementation: [Platform](#platform) and +[User-Facing](#userfacing) + +## Platform +The [platform](/api-reference/groups/platform/group-create) APIs accept Rownd application credentials for authentication. They are intended for use by an +application administrator. You should use these APIs on your backend server or equivalent to manage groups, +members, and invites + +## User-Facing +The [user-facing](/api-reference/groups/user/group-create) APIs accept an authenticated user's Rownd access token (JWT) for authentication. This set of APIs is intended for use in frontend applications when you want to give your +users the ability to manage their own groups, members, and invites. + +### User-Facing Distinctions +The user-facing APIs differ slightly in implementation. Here are the main differences: + +#### Authorization +Group members and invites can only be managed by group owners. A group owner is a group member that has the +`"owner"` role. + +#### Group Owners +The creator of a group is always given the `"owner"` role. + +## Getting Started + +Here are a few key endpoints to help you get started integrating Groups into your app: + + + Platform API for creating a group + + + Platform API for creating a group invite + + + Platform API for updating a group member + + + Platform API for deleting a group member + + \ No newline at end of file diff --git a/rownd-docusaurus/api-reference/groups/platform/group-create.mdx b/rownd-docusaurus/api-reference/groups/platform/group-create.mdx new file mode 100644 index 0000000..9f84bde --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/group-create.mdx @@ -0,0 +1,49 @@ +--- +title: "Create a group" +openapi: "POST /applications/{app}/groups" +--- + +Platform API for creating a new group. + +### Endpoint + +- Method: `POST` +- Path: `/applications/{app}/groups` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "name": "Early Access", + "description": "Beta testers" +} +``` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/applications/{app}/groups" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"name":"Early Access","description":"Beta testers"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "grp_123", + "name": "Early Access", + "description": "Beta testers" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/group-delete.mdx b/rownd-docusaurus/api-reference/groups/platform/group-delete.mdx new file mode 100644 index 0000000..de438f4 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/group-delete.mdx @@ -0,0 +1,30 @@ +--- +title: "Delete a group" +openapi: "DELETE /applications/{app}/groups/{group}" +--- + +Platform API for deleting a group. + +### Endpoint + +- Method: `DELETE` +- Path: `/applications/{app}/groups/{group}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/applications/{app}/groups/{group}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/groups/platform/group-list.mdx b/rownd-docusaurus/api-reference/groups/platform/group-list.mdx new file mode 100644 index 0000000..fc10ec3 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/group-list.mdx @@ -0,0 +1,45 @@ +--- +title: "List groups" +openapi: "GET /applications/{app}/groups" +--- + +Platform API for listing all groups belonging to an app. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/groups` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor +- `filter` (optional): Lookup filter + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/groups?limit=25" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"id": "grp_123", "name": "Early Access"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/group-read.mdx b/rownd-docusaurus/api-reference/groups/platform/group-read.mdx new file mode 100644 index 0000000..f8ab904 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/group-read.mdx @@ -0,0 +1,38 @@ +--- +title: "Retrieve a group" +openapi: "GET /applications/{app}/groups/{group}" +--- + +Platform API for retrieving a group. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/groups/{group}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/groups/{group}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "id": "grp_123", + "name": "Early Access", + "description": "Beta testers" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/group-update.mdx b/rownd-docusaurus/api-reference/groups/platform/group-update.mdx new file mode 100644 index 0000000..5bd6a14 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/group-update.mdx @@ -0,0 +1,49 @@ +--- +title: "Update a group" +openapi: "PUT /applications/{app}/groups/{group}" +--- + +Platform API for updating a group. + +### Endpoint + +- Method: `PUT` +- Path: `/applications/{app}/groups/{group}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "name": "Early Access", + "description": "Updated description" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/applications/{app}/groups/{group}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"name":"Early Access","description":"Updated description"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "grp_123", + "name": "Early Access", + "description": "Updated description" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/invites/invite-create.mdx b/rownd-docusaurus/api-reference/groups/platform/invites/invite-create.mdx new file mode 100644 index 0000000..e62f46c --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/invites/invite-create.mdx @@ -0,0 +1,48 @@ +--- +title: "Create a group invite" +openapi: "POST /applications/{app}/groups/{group}/invites" +--- + +Create a new invite for a group (app-scoped). + +### Endpoint + +- Method: `POST` +- Path: `/applications/{app}/groups/{group}/invites` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "email": "invitee@example.com" +} +``` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/invites" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"email":"invitee@example.com"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "inv_123", + "email": "invitee@example.com", + "status": "pending" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/invites/invite-delete.mdx b/rownd-docusaurus/api-reference/groups/platform/invites/invite-delete.mdx new file mode 100644 index 0000000..d301f6b --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/invites/invite-delete.mdx @@ -0,0 +1,30 @@ +--- +title: "Delete a group invite" +openapi: "DELETE /applications/{app}/groups/{group}/invites/{invite}" +--- + +Delete a group invite (app-scoped). + +### Endpoint + +- Method: `DELETE` +- Path: `/applications/{app}/groups/{group}/invites/{invite}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/invites/{invite}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/groups/platform/invites/invite-list.mdx b/rownd-docusaurus/api-reference/groups/platform/invites/invite-list.mdx new file mode 100644 index 0000000..9d1dfd5 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/invites/invite-list.mdx @@ -0,0 +1,44 @@ +--- +title: "List group invites" +openapi: "GET /applications/{app}/groups/{group}/invites" +--- + +List invites for a group (app-scoped). + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/groups/{group}/invites` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/invites?limit=25" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"id": "inv_123", "email": "invitee@example.com", "status": "pending"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/invites/invite-read.mdx b/rownd-docusaurus/api-reference/groups/platform/invites/invite-read.mdx new file mode 100644 index 0000000..7fcab59 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/invites/invite-read.mdx @@ -0,0 +1,38 @@ +--- +title: "Retrieve a group invite" +openapi: "GET /applications/{app}/groups/{group}/invites/{invite}" +--- + +Retrieve a specific group invite (app-scoped). + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/groups/{group}/invites/{invite}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/invites/{invite}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "id": "inv_123", + "email": "invitee@example.com", + "status": "pending" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/invites/invite-update.mdx b/rownd-docusaurus/api-reference/groups/platform/invites/invite-update.mdx new file mode 100644 index 0000000..3250f9b --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/invites/invite-update.mdx @@ -0,0 +1,47 @@ +--- +title: "Update a group invite" +openapi: "PUT /applications/{app}/groups/{group}/invites/{invite}" +--- + +Update a group invite (app-scoped). + +### Endpoint + +- Method: `PUT` +- Path: `/applications/{app}/groups/{group}/invites/{invite}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "status": "accepted" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/invites/{invite}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"status":"accepted"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "inv_123", + "status": "accepted" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/members/member-create.mdx b/rownd-docusaurus/api-reference/groups/platform/members/member-create.mdx new file mode 100644 index 0000000..d2342bb --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/members/member-create.mdx @@ -0,0 +1,47 @@ +--- +title: "Create a group member" +openapi: "POST /applications/{app}/groups/{group}/members" +--- + +Add a member to a group (app-scoped). + +### Endpoint + +- Method: `POST` +- Path: `/applications/{app}/groups/{group}/members` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "user": "usr_123" +} +``` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/members" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"user":"usr_123"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "mem_123", + "user": "usr_123" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/members/member-delete.mdx b/rownd-docusaurus/api-reference/groups/platform/members/member-delete.mdx new file mode 100644 index 0000000..5cf6228 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/members/member-delete.mdx @@ -0,0 +1,30 @@ +--- +title: "Delete a group member" +openapi: "DELETE /applications/{app}/groups/{group}/members/{member}" +--- + +Remove a member from a group (app-scoped). + +### Endpoint + +- Method: `DELETE` +- Path: `/applications/{app}/groups/{group}/members/{member}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/members/{member}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/groups/platform/members/member-list.mdx b/rownd-docusaurus/api-reference/groups/platform/members/member-list.mdx new file mode 100644 index 0000000..4ccfb7e --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/members/member-list.mdx @@ -0,0 +1,44 @@ +--- +title: "List group member" +openapi: "GET /applications/{app}/groups/{group}/members" +--- + +List members of a group (app-scoped). + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/groups/{group}/members` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/members?limit=25" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"id": "mem_123", "user": "usr_123"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/members/member-read.mdx b/rownd-docusaurus/api-reference/groups/platform/members/member-read.mdx new file mode 100644 index 0000000..29b6538 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/members/member-read.mdx @@ -0,0 +1,37 @@ +--- +title: "Retrieve a group member" +openapi: "GET /applications/{app}/groups/{group}/members/{member}" +--- + +Retrieve a group member (app-scoped). + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/groups/{group}/members/{member}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/members/{member}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "id": "mem_123", + "user": "usr_123" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/platform/members/member-update.mdx b/rownd-docusaurus/api-reference/groups/platform/members/member-update.mdx new file mode 100644 index 0000000..37fb25e --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/platform/members/member-update.mdx @@ -0,0 +1,47 @@ +--- +title: "Update a group member" +openapi: "PUT /applications/{app}/groups/{group}/members/{member}" +--- + +Update a group member (app-scoped). + +### Endpoint + +- Method: `PUT` +- Path: `/applications/{app}/groups/{group}/members/{member}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "role": "admin" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/applications/{app}/groups/{group}/members/{member}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"role":"admin"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "mem_123", + "role": "admin" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/group-create.mdx b/rownd-docusaurus/api-reference/groups/user/group-create.mdx new file mode 100644 index 0000000..e9f9b9a --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/group-create.mdx @@ -0,0 +1,45 @@ +--- +title: "Create a group" +openapi: "POST /me/groups" +--- + +User-scoped API for creating a group owned by the current user. + +### Endpoint + +- Method: `POST` +- Path: `/me/groups` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "name": "My Group" +} +``` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/me/groups" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"name":"My Group"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "grp_abc", + "name": "My Group" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/group-delete.mdx b/rownd-docusaurus/api-reference/groups/user/group-delete.mdx new file mode 100644 index 0000000..91dd6a6 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/group-delete.mdx @@ -0,0 +1,28 @@ +--- +title: "Delete a group" +openapi: "DELETE /me/groups/{group}" +--- + +User-scoped API for deleting a group. + +### Endpoint + +- Method: `DELETE` +- Path: `/me/groups/{group}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/me/groups/{group}" \ + --header "Authorization: Bearer " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/groups/user/group-list.mdx b/rownd-docusaurus/api-reference/groups/user/group-list.mdx new file mode 100644 index 0000000..89aeff9 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/group-list.mdx @@ -0,0 +1,42 @@ +--- +title: "List groups" +openapi: "GET /me/groups" +--- + +User-scoped API for listing groups owned by the current user. + +### Endpoint + +- Method: `GET` +- Path: `/me/groups` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/me/groups?limit=25" \ + --header "Authorization: Bearer " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"id": "grp_abc", "name": "My Group"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/group-read.mdx b/rownd-docusaurus/api-reference/groups/user/group-read.mdx new file mode 100644 index 0000000..d66b21f --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/group-read.mdx @@ -0,0 +1,35 @@ +--- +title: "Retrieve a group" +openapi: "GET /me/groups/{group}" +--- + +User-scoped API for retrieving a group by ID. + +### Endpoint + +- Method: `GET` +- Path: `/me/groups/{group}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/me/groups/{group}" \ + --header "Authorization: Bearer " +``` + +### Response + +200 - application/json + +```json +{ + "id": "grp_abc", + "name": "My Group" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/group-update.mdx b/rownd-docusaurus/api-reference/groups/user/group-update.mdx new file mode 100644 index 0000000..1bf8ce2 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/group-update.mdx @@ -0,0 +1,45 @@ +--- +title: "Update a group" +openapi: "PUT /me/groups/{group}" +--- + +User-scoped API for updating a group. + +### Endpoint + +- Method: `PUT` +- Path: `/me/groups/{group}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "name": "Updated Group" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/me/groups/{group}" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"name":"Updated Group"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "grp_abc", + "name": "Updated Group" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/invites/invite-create.mdx b/rownd-docusaurus/api-reference/groups/user/invites/invite-create.mdx new file mode 100644 index 0000000..0e0031d --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/invites/invite-create.mdx @@ -0,0 +1,46 @@ +--- +title: "Create a group invite" +openapi: "POST /me/groups/{group}/invites" +--- + +Create a new invite for a group (user-scoped). + +### Endpoint + +- Method: `POST` +- Path: `/me/groups/{group}/invites` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "email": "invitee@example.com" +} +``` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/me/groups/{group}/invites" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"email":"invitee@example.com"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "inv_abc", + "email": "invitee@example.com", + "status": "pending" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/invites/invite-delete.mdx b/rownd-docusaurus/api-reference/groups/user/invites/invite-delete.mdx new file mode 100644 index 0000000..eef8f47 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/invites/invite-delete.mdx @@ -0,0 +1,28 @@ +--- +title: "Delete a group invite" +openapi: "DELETE /me/groups/{group}/invites/{invite}" +--- + +Delete a group invite (user-scoped). + +### Endpoint + +- Method: `DELETE` +- Path: `/me/groups/{group}/invites/{invite}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/me/groups/{group}/invites/{invite}" \ + --header "Authorization: Bearer " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/groups/user/invites/invite-list.mdx b/rownd-docusaurus/api-reference/groups/user/invites/invite-list.mdx new file mode 100644 index 0000000..9910e52 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/invites/invite-list.mdx @@ -0,0 +1,42 @@ +--- +title: "List group invites" +openapi: "GET /me/groups/{group}/invites" +--- + +List invites for a group (user-scoped). + +### Endpoint + +- Method: `GET` +- Path: `/me/groups/{group}/invites` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/me/groups/{group}/invites?limit=25" \ + --header "Authorization: Bearer " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"id": "inv_abc", "email": "invitee@example.com", "status": "pending"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/invites/invite-read.mdx b/rownd-docusaurus/api-reference/groups/user/invites/invite-read.mdx new file mode 100644 index 0000000..6507e8f --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/invites/invite-read.mdx @@ -0,0 +1,36 @@ +--- +title: "Retrieve a group invite" +openapi: "GET /me/groups/{group}/invites/{invite}" +--- + +Retrieve a group invite (user-scoped). + +### Endpoint + +- Method: `GET` +- Path: `/me/groups/{group}/invites/{invite}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/me/groups/{group}/invites/{invite}" \ + --header "Authorization: Bearer " +``` + +### Response + +200 - application/json + +```json +{ + "id": "inv_abc", + "email": "invitee@example.com", + "status": "pending" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/invites/invite-update.mdx b/rownd-docusaurus/api-reference/groups/user/invites/invite-update.mdx new file mode 100644 index 0000000..13540c3 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/invites/invite-update.mdx @@ -0,0 +1,45 @@ +--- +title: "Update a group invite" +openapi: "PUT /me/groups/{group}/invites/{invite}" +--- + +Update a group invite (user-scoped). + +### Endpoint + +- Method: `PUT` +- Path: `/me/groups/{group}/invites/{invite}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "status": "accepted" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/me/groups/{group}/invites/{invite}" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"status":"accepted"}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "inv_abc", + "status": "accepted" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/members/member-create.mdx b/rownd-docusaurus/api-reference/groups/user/members/member-create.mdx new file mode 100644 index 0000000..e7ed616 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/members/member-create.mdx @@ -0,0 +1,35 @@ +--- +title: "Create a group member" +openapi: "POST /me/groups/{group}/members" +--- + +Create a member in a group (user-scoped). + + + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "user": "usr_123" +} +``` + +```bash title="cURL" +curl --request POST \ + --url "https://api.rownd.io/me/groups/{group}/members" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"user":"usr_123"}' +``` + +```json title="200 OK" +{ + "id": "mem_abc", + "user": "usr_123" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/members/member-delete.mdx b/rownd-docusaurus/api-reference/groups/user/members/member-delete.mdx new file mode 100644 index 0000000..3fab711 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/members/member-delete.mdx @@ -0,0 +1,22 @@ +--- +title: "Delete a group member" +openapi: "DELETE /me/groups/{group}/members/{member}" +--- + +Remove a member from a group (user-scoped). + + + +### Headers + +- `Authorization: Bearer ` + +```bash title="cURL" +curl --request DELETE \ + --url "https://api.rownd.io/me/groups/{group}/members/{member}" \ + --header "Authorization: Bearer " +``` + +```text title="204 No Content" + +``` diff --git a/rownd-docusaurus/api-reference/groups/user/members/member-list.mdx b/rownd-docusaurus/api-reference/groups/user/members/member-list.mdx new file mode 100644 index 0000000..ca6988e --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/members/member-list.mdx @@ -0,0 +1,32 @@ +--- +title: "List group members" +openapi: "GET /me/groups/{group}/members" +--- + +List members of a group (user-scoped). + + + +### Headers + +- `Authorization: Bearer ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor + +```bash title="cURL" +curl --request GET \ + --url "https://api.rownd.io/me/groups/{group}/members?limit=25" \ + --header "Authorization: Bearer " +``` + +```json title="200 OK" +{ + "data": [ + {"id": "mem_abc", "user": "usr_123"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/members/member-read.mdx b/rownd-docusaurus/api-reference/groups/user/members/member-read.mdx new file mode 100644 index 0000000..4e255fd --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/members/member-read.mdx @@ -0,0 +1,25 @@ +--- +title: "Retrieve a group member" +openapi: "GET /me/groups/{group}/members/{member}" +--- + +Retrieve a group member (user-scoped). + + + +### Headers + +- `Authorization: Bearer ` + +```bash title="cURL" +curl --request GET \ + --url "https://api.rownd.io/me/groups/{group}/members/{member}" \ + --header "Authorization: Bearer " +``` + +```json title="200 OK" +{ + "id": "mem_abc", + "user": "usr_123" +} +``` diff --git a/rownd-docusaurus/api-reference/groups/user/members/member-update.mdx b/rownd-docusaurus/api-reference/groups/user/members/member-update.mdx new file mode 100644 index 0000000..6789901 --- /dev/null +++ b/rownd-docusaurus/api-reference/groups/user/members/member-update.mdx @@ -0,0 +1,35 @@ +--- +title: "Update a group member" +openapi: "PUT /me/groups/{group}/members/{member}" +--- + +Update a group member (user-scoped). + + + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "role": "admin" +} +``` + +```bash title="cURL" +curl --request PUT \ + --url "https://api.rownd.io/me/groups/{group}/members/{member}" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"role":"admin"}' +``` + +```json title="200 OK" +{ + "id": "mem_abc", + "role": "admin" +} +``` diff --git a/rownd-docusaurus/api-reference/oidc/clients/create.mdx b/rownd-docusaurus/api-reference/oidc/clients/create.mdx new file mode 100644 index 0000000..1fe8aa8 --- /dev/null +++ b/rownd-docusaurus/api-reference/oidc/clients/create.mdx @@ -0,0 +1,48 @@ +--- +title: "Create an OpenID Connect client" +openapi: "POST /applications/{app}/oidc-clients" +--- + +Create a new OIDC client for your application. + +### Endpoint + +- Method: `POST` +- Path: `/applications/{app}/oidc-clients` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "name": "My App", + "redirect_uris": ["https://example.com/callback"] +} +``` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/applications/{app}/oidc-clients" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"name":"My App","redirect_uris":["https://example.com/callback"]}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "cli_123", + "name": "My App" +} +``` diff --git a/rownd-docusaurus/api-reference/oidc/clients/delete.mdx b/rownd-docusaurus/api-reference/oidc/clients/delete.mdx new file mode 100644 index 0000000..1518681 --- /dev/null +++ b/rownd-docusaurus/api-reference/oidc/clients/delete.mdx @@ -0,0 +1,30 @@ +--- +title: "Delete an OpenID Connect client" +openapi: "DELETE /applications/{app}/oidc-clients/{client}" +--- + +Delete an OIDC client. + +### Endpoint + +- Method: `DELETE` +- Path: `/applications/{app}/oidc-clients/{client}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/applications/{app}/oidc-clients/{client}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/oidc/clients/list.mdx b/rownd-docusaurus/api-reference/oidc/clients/list.mdx new file mode 100644 index 0000000..8739d8e --- /dev/null +++ b/rownd-docusaurus/api-reference/oidc/clients/list.mdx @@ -0,0 +1,44 @@ +--- +title: "List OpenID Connect clients" +openapi: "GET /applications/{app}/oidc-clients" +--- + +Retrieve a paginated list of OIDC clients for an application. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/oidc-clients` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Cursor for pagination + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/oidc-clients?limit=25" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"id": "cli_123", "name": "My App"} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/oidc/clients/overview.mdx b/rownd-docusaurus/api-reference/oidc/clients/overview.mdx new file mode 100644 index 0000000..e69de29 diff --git a/rownd-docusaurus/api-reference/oidc/clients/read.mdx b/rownd-docusaurus/api-reference/oidc/clients/read.mdx new file mode 100644 index 0000000..c4de4b5 --- /dev/null +++ b/rownd-docusaurus/api-reference/oidc/clients/read.mdx @@ -0,0 +1,37 @@ +--- +title: "Retrieve an OpenID Connect client" +openapi: "GET /applications/{app}/oidc-clients/{client}" +--- + +Retrieve a specific OIDC client by ID. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/oidc-clients/{client}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/oidc-clients/{client}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "id": "cli_123", + "name": "My App" +} +``` diff --git a/rownd-docusaurus/api-reference/oidc/clients/update.mdx b/rownd-docusaurus/api-reference/oidc/clients/update.mdx new file mode 100644 index 0000000..710485e --- /dev/null +++ b/rownd-docusaurus/api-reference/oidc/clients/update.mdx @@ -0,0 +1,48 @@ +--- +title: "Update an OpenID Connect client" +openapi: "PUT /applications/{app}/oidc-clients/{client}" +--- + +Update an existing OIDC client. + +### Endpoint + +- Method: `PUT` +- Path: `/applications/{app}/oidc-clients/{client}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "name": "My App", + "redirect_uris": ["https://example.com/callback"] +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/applications/{app}/oidc-clients/{client}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"name":"My App","redirect_uris":["https://example.com/callback"]}' +``` + +### Response + +200 - application/json + +```json +{ + "id": "cli_123", + "name": "My App" +} +``` diff --git a/rownd-docusaurus/api-reference/oidc/overview.mdx b/rownd-docusaurus/api-reference/oidc/overview.mdx new file mode 100644 index 0000000..e69de29 diff --git a/rownd-docusaurus/api-reference/user-profiles/app/delete.mdx b/rownd-docusaurus/api-reference/user-profiles/app/delete.mdx new file mode 100644 index 0000000..1bf3d00 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/delete.mdx @@ -0,0 +1,30 @@ +--- +title: "Delete a user profile" +openapi: "DELETE /applications/{app}/users/{user}/data" +--- + +Delete a user's profile data for your application. + +### Endpoint + +- Method: `DELETE` +- Path: `/applications/{app}/users/{user}/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request DELETE \ + --url "https://api.rownd.io/applications/{app}/users/{user}/data" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/api-reference/user-profiles/app/get-sample-data.mdx b/rownd-docusaurus/api-reference/user-profiles/app/get-sample-data.mdx new file mode 100644 index 0000000..204bfd3 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/get-sample-data.mdx @@ -0,0 +1,4 @@ +--- +title: "Get sample user profile data" +openapi: "GET /applications/{app}/users/__sample__/data" +--- diff --git a/rownd-docusaurus/api-reference/user-profiles/app/get-user-data.mdx b/rownd-docusaurus/api-reference/user-profiles/app/get-user-data.mdx new file mode 100644 index 0000000..0a3dc86 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/get-user-data.mdx @@ -0,0 +1,40 @@ +--- +title: "Retrieve a user profile" +openapi: "GET /applications/{app}/users/{user}/data" +--- + +Retrieve a user's profile data for your application. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/users/{user}/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/users/{user}/data" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "user": "usr_123", + "data": { + "email": "user@example.com", + "first_name": "Jane" + } +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/app/insert-update.mdx b/rownd-docusaurus/api-reference/user-profiles/app/insert-update.mdx new file mode 100644 index 0000000..a5ed972 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/insert-update.mdx @@ -0,0 +1,51 @@ +--- +title: "Insert or update user profile data" +openapi: "PUT /applications/{app}/users/{user}/data" +--- + +Insert or update a user's profile data for your application. + +### Endpoint + +- Method: `PUT` +- Path: `/applications/{app}/users/{user}/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "email": "user@example.com", + "first_name": "Jane" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/applications/{app}/users/{user}/data" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"email":"user@example.com","first_name":"Jane"}' +``` + +### Response + +200 - application/json + +```json +{ + "user": "usr_123", + "data": { + "email": "user@example.com", + "first_name": "Jane" + } +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/app/list-user-profiles.mdx b/rownd-docusaurus/api-reference/user-profiles/app/list-user-profiles.mdx new file mode 100644 index 0000000..ef0d042 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/list-user-profiles.mdx @@ -0,0 +1,44 @@ +--- +title: "List user profiles" +openapi: "GET /applications/{app}/users/data" +--- + +Retrieve a paginated list of user profiles for your application. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/users/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Query params + +- `limit` (optional): Page size (max 100) +- `after` (optional): Pagination cursor + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/users/data?limit=25" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "data": [ + {"user": "usr_123", "data": {"email": "user@example.com"}} + ], + "paging": {"next": null} +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/app/retrieve-data-policies.mdx b/rownd-docusaurus/api-reference/user-profiles/app/retrieve-data-policies.mdx new file mode 100644 index 0000000..4298816 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/retrieve-data-policies.mdx @@ -0,0 +1,18 @@ +--- +title: "Retrieve the data policies for a user's profile" +api: "GET https://api.rownd.io/applications/{app}/users/{user}/acls" +--- + +### Path Parameters + + + + + +### Response attributes + + + + + + diff --git a/rownd-docusaurus/api-reference/user-profiles/app/retrieve-field.mdx b/rownd-docusaurus/api-reference/user-profiles/app/retrieve-field.mdx new file mode 100644 index 0000000..2e8f254 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/retrieve-field.mdx @@ -0,0 +1,37 @@ +--- +title: "Retrieve one field from a user profile" +openapi: "GET /applications/{app}/users/{user}/data/fields/{field}" +--- + +Retrieve a single field from a user's profile. + +### Endpoint + +- Method: `GET` +- Path: `/applications/{app}/users/{user}/data/fields/{field}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/applications/{app}/users/{user}/data/fields/{field}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +200 - application/json + +```json +{ + "field": "email", + "value": "user@example.com" +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/app/update-field.mdx b/rownd-docusaurus/api-reference/user-profiles/app/update-field.mdx new file mode 100644 index 0000000..4b688f1 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/update-field.mdx @@ -0,0 +1,47 @@ +--- +title: "Update one field in a user profile" +openapi: "PUT /applications/{app}/users/{user}/data/fields/{field}" +--- + +Update a single field in a user's profile. + +### Endpoint + +- Method: `PUT` +- Path: `/applications/{app}/users/{user}/data/fields/{field}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "value": "user@example.com" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/applications/{app}/users/{user}/data/fields/{field}" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"value":"user@example.com"}' +``` + +### Response + +200 - application/json + +```json +{ + "field": "email", + "value": "user@example.com" +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/app/update-patch.mdx b/rownd-docusaurus/api-reference/user-profiles/app/update-patch.mdx new file mode 100644 index 0000000..769b21c --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/app/update-patch.mdx @@ -0,0 +1,49 @@ +--- +title: "Update / patch user profile data" +openapi: "PATCH /applications/{app}/users/{user}/data" +--- + +Patch a user's profile data. + +### Endpoint + +- Method: `PATCH` +- Path: `/applications/{app}/users/{user}/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Request body + +```json +{ + "first_name": "Janet" +} +``` + +### Try it + +```bash +curl --request PATCH \ + --url "https://api.rownd.io/applications/{app}/users/{user}/data" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " \ + --header "Content-Type: application/json" \ + --data '{"first_name":"Janet"}' +``` + +### Response + +200 - application/json + +```json +{ + "user": "usr_123", + "data": { + "first_name": "Janet" + } +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/user/get-user-data.mdx b/rownd-docusaurus/api-reference/user-profiles/user/get-user-data.mdx new file mode 100644 index 0000000..97c883c --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/user/get-user-data.mdx @@ -0,0 +1,38 @@ +--- +title: "Retrieve a user profile" +openapi: "GET /me/applications/{app}/data" +--- + +Retrieve the current user's profile data for the given application. + +### Endpoint + +- Method: `GET` +- Path: `/me/applications/{app}/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/me/applications/{app}/data" \ + --header "Authorization: Bearer " +``` + +### Response + +200 - application/json + +```json +{ + "user": "usr_123", + "data": { + "email": "user@example.com", + "first_name": "Jane" + } +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/user/retrieve-field.mdx b/rownd-docusaurus/api-reference/user-profiles/user/retrieve-field.mdx new file mode 100644 index 0000000..a5b130a --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/user/retrieve-field.mdx @@ -0,0 +1,35 @@ +--- +title: "Retrieve one field from a user profile" +openapi: "GET /me/applications/{app}/data/fields/{field}" +--- + +Retrieve a single profile field for the current user. + +### Endpoint + +- Method: `GET` +- Path: `/me/applications/{app}/data/fields/{field}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Try it + +```bash +curl --request GET \ + --url "https://api.rownd.io/me/applications/{app}/data/fields/{field}" \ + --header "Authorization: Bearer " +``` + +### Response + +200 - application/json + +```json +{ + "field": "email", + "value": "user@example.com" +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/user/update-field.mdx b/rownd-docusaurus/api-reference/user-profiles/user/update-field.mdx new file mode 100644 index 0000000..9d8bed3 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/user/update-field.mdx @@ -0,0 +1,45 @@ +--- +title: "Update one field in a user profile" +openapi: "PUT /me/applications/{app}/data/fields/{field}" +--- + +Update a single profile field for the current user. + +### Endpoint + +- Method: `PUT` +- Path: `/me/applications/{app}/data/fields/{field}` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "value": "user@example.com" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/me/applications/{app}/data/fields/{field}" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"value":"user@example.com"}' +``` + +### Response + +200 - application/json + +```json +{ + "field": "email", + "value": "user@example.com" +} +``` diff --git a/rownd-docusaurus/api-reference/user-profiles/user/update-put.mdx b/rownd-docusaurus/api-reference/user-profiles/user/update-put.mdx new file mode 100644 index 0000000..bb40e1d --- /dev/null +++ b/rownd-docusaurus/api-reference/user-profiles/user/update-put.mdx @@ -0,0 +1,49 @@ +--- +title: Update user profile data +openapi: "PUT /me/applications/{app}/data" +--- + +Replace the current user's profile data. + +### Endpoint + +- Method: `PUT` +- Path: `/me/applications/{app}/data` +- Base URL: `https://api.rownd.io` + +### Headers + +- `Authorization: Bearer ` + +### Request body + +```json +{ + "first_name": "Jane", + "last_name": "Doe" +} +``` + +### Try it + +```bash +curl --request PUT \ + --url "https://api.rownd.io/me/applications/{app}/data" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + --data '{"first_name":"Jane","last_name":"Doe"}' +``` + +### Response + +200 - application/json + +```json +{ + "user": "usr_123", + "data": { + "first_name": "Jane", + "last_name": "Doe" + } +} +``` diff --git a/rownd-docusaurus/api-reference/user-sessions/app/revoke-user-sessions.mdx b/rownd-docusaurus/api-reference/user-sessions/app/revoke-user-sessions.mdx new file mode 100644 index 0000000..253e010 --- /dev/null +++ b/rownd-docusaurus/api-reference/user-sessions/app/revoke-user-sessions.mdx @@ -0,0 +1,30 @@ +--- +title: "Revoke all user tokens/sessions" +openapi: "POST /applications/{app}/users/{user}/signout" +--- + +Revoke all active access tokens/sessions for a user. + +### Endpoint + +- Method: `POST` +- Path: `/applications/{app}/users/{user}/signout` +- Base URL: `https://api.rownd.io` + +### Headers + +- `X-Rownd-App-Key: ` +- `X-Rownd-App-Secret: ` + +### Try it + +```bash +curl --request POST \ + --url "https://api.rownd.io/applications/{app}/users/{user}/signout" \ + --header "X-Rownd-App-Key: " \ + --header "X-Rownd-App-Secret: " +``` + +### Response + +204 - No Content diff --git a/rownd-docusaurus/docs/_snippets/javascript--api--near.mdx b/rownd-docusaurus/docs/_snippets/javascript--api--near.mdx new file mode 100644 index 0000000..854a138 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/javascript--api--near.mdx @@ -0,0 +1,56 @@ + + The `near` API allows you to interact with the Rownd's [NEAR integration](/configuration/web3/near-overview). + + + Creates an implicit NEAR account for the current user if one doesn't already exist + + + ```javascript + const accountId = rownd.near.ensureImplicitAccount() + ``` + + + + + Prompts the user to create a named NEAR account + + + ```javascript + const accountId = rownd.near.createNamedAccount() + ``` + + + + + Prompts the user to connect a NEAR account + + + ```javascript + const accountId = rownd.near.connectAccount() + ``` + + + + + + + + + + + + + + + + + + Opens a dialog showing the details of the user's implicit NEAR account + + + ```javascript + const accountId = rownd.near.walletDetails() + ``` + + + \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/migration/completion.mdx b/rownd-docusaurus/docs/_snippets/migration/completion.mdx new file mode 100644 index 0000000..e1defbc --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/migration/completion.mdx @@ -0,0 +1,2 @@ +## Completing the migration +At this point, you should be ready to deploy your new Rownd-enabled product to production! If you have any questions or concerns, please [get in touch](mailto:support@rownd.io?subject=Help%20with%20migration). \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/migration/setup-rownd-steps.mdx b/rownd-docusaurus/docs/_snippets/migration/setup-rownd-steps.mdx new file mode 100644 index 0000000..4755185 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/migration/setup-rownd-steps.mdx @@ -0,0 +1,4 @@ +1. Sign into the [Rownd Platform](https://app.rownd.io). If this is your first visit, an account and app will be created for you automatically. +2. Create a new [Rownd app](/configuration/applications#create-a-new-application) for your product. You'll probably want to create a separate app for your test and production environments. +3. [Enable the sign-in methods](/configuration/authentication-methods) that you want to support. If you already have Google or Apple sign-in enabled, you can use the same credentials in Rownd. +4. [Customize the sign-in experience](/configuration/authentication-methods) to match your brand with logos and colors. \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/migration/testing.mdx b/rownd-docusaurus/docs/_snippets/migration/testing.mdx new file mode 100644 index 0000000..94881d7 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/migration/testing.mdx @@ -0,0 +1,8 @@ +## Test the migration +Once everything is set up, it's time to test various aspects of the migration. Here are some things to consider: + +1. Make sure new users can sign in successfully. If you use an email provider that supports sub-addressing, you can make up "new" users like `juliet+test1@gmail.com` and the messages will be delivered to `juliet@gmail.com`. + +2. Verify existing users can sign in successfully and that they receive the same user ID that they had prior to the migration. + +3. If you chose to keep existing users signed in, test the migration flow to ensure that you remain signed in throughout the process. This usually means loading or installing the previous version of your product, signing in with your old provider, then loading the Rownd-enabled version of the app. \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/mobile/react-native/react-native.mdx b/rownd-docusaurus/docs/_snippets/mobile/react-native/react-native.mdx new file mode 100644 index 0000000..13acccf --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/mobile/react-native/react-native.mdx @@ -0,0 +1,178 @@ +#### Usage + +The Rownd SDK includes a context provider that will enable any component of your +app to access authentication state and user data. + +Before you can use the SDK, you'll need to obtain an App Key from the +[Rownd Dashboard](https://app.rownd.io). + +```jsx +import { RowndProvider } from "@rownd/react-native"; + +// ... + +export default function Root() { + return ( + + + + ); +} +``` + +Later on within your app's components, you can use the Rownd hook to access the +Rownd browser API: + +```jsx +import { View, Text } from "react-native"; +import { useRownd } from "@rownd/react"; + +export default function MyProtectedComponent(props) { + const { is_authenticated, user, requestSignIn, getAccessToken } = useRownd(); + + // You can also request a sign in without a user pressing a button + // by calling requestSignIn() from a useEffect callback. + // useEffect(() => { + // if (!is_authenticated) { + // requestSignIn(); + // } + // }, [is_authenticated]); + + return ( + + {is_authenticated ? ( + <> +

Welcome {user.data.first_name}

+ + + ) : ( + <> + Please sign in to continue + requestSignIn()}> + Sign in + + + )} +
+ ); +} +``` + +#### API reference + +Most API methods are made available via the Rownd Provider and its associated +`useRownd` React hook. Unless otherwise noted, we're assuming that you're using +hooks. + +**requestSignIn()** + +Trigger the Rownd sign in dialog + +| Property | Type | Description | +| --- | --- | --- | +| `method` | `email` `phone` `apple` `google` `passkey` | Requests a sign-in, but with a specific authentication provider (e.g., Sign in with Apple). Rownd treats this information as a method. If the specified authentication provider is enabled within your Rownd app configuration, it will be honored. If not, Rownd will fall back to the default flow. | +| `intent` | `sign_in` `sign_up` | This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `sign_in` or `Sign_up`. If you don’t set this value, the user will be presented with the unified sign-in/sign-up flow. Please reach out to [support@rownd.io](mailto:support@rownd.io) to enable. | +| `postSignInRedirect (Not recommended)` | `String` | If a subdomain is provided in the Rownd dashboard, this behavior will work by default. The URL to redirect to after the user has signed in. This can be used for deep-linking within the app or to ensure that the user is redirected back into the app after completing a sign-in from email or text message. | + +```tsx +const { requestSignIn } = useRownd(); + +requestSignIn({ + method: 'apple' +}); +``` + +**signOut()** + +Sign out the user and clear their profile, returning them to a completely +unauthenticated state. + +```jsx +const { signOut } = useRownd(); +signOut(); +``` + +**getAccessToken()** + +Retrieves the active, valid access token for the current user. + +```jsx +const { getAccessToken } = useRownd(); + +let accessToken = await getAccessToken(); +``` + +**is_authenticated** + +Indicates whether the current user is signed in or not. + +```jsx +const { is_authenticated } = useRownd(); + +return ( + <> + {is_authenticated && } + {!is_authenticated && } + +); +``` + +**access_token** + +Represents the current access token for the user. + +```jsx +const { access_token } = useRownd(); + +useEffect(() => { + axios({ + method: 'post', + url: '/api/sessions' + headers: { + authorization: `Bearer ${access_token}` + } + }).then(console.log); +}, [access_token]); +``` + +**user** + +Represents information about the current user, specifically their profile +information. In the example below, we use the existing data to display the +current value of `first_name` in a form field, update a local copy of that data +as the user changes it, and then save the changes to Rownd once the user submits +the form. + +```jsx +const { user } = useRownd(); + +return ( +
user.set(profile)}> + First name + + Save + +); +``` + +**Merge data into the user profile** + +```jsx +const { user } = useRownd(); +user.set({ + first_name: "Alice", + last_name: "Ranier", +}); +``` + +Set a specific field in the user profile + +```jsx +const { user } = useRownd(); +user.setValue("first_name", "Alice"); +``` diff --git a/rownd-docusaurus/docs/_snippets/unverified-users-description.mdx b/rownd-docusaurus/docs/_snippets/unverified-users-description.mdx new file mode 100644 index 0000000..9abd541 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/unverified-users-description.mdx @@ -0,0 +1,3 @@ +Rownd's Unverified Users feature allows new users to sign in with their email without immediately needing to verify. Existing users, or sign-in attempts with an email for which a user already exists will be required to verify immediately. + +With Unverified Users you can reduce friction in your onboarding experience and dramatically improve conversion rates. Drive customers deeper into your onboarding funnel and give them incentive to stay before forcing them to verify. diff --git a/rownd-docusaurus/docs/_snippets/web/params/app-key.mdx b/rownd-docusaurus/docs/_snippets/web/params/app-key.mdx new file mode 100644 index 0000000..f6f1e4f --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/app-key.mdx @@ -0,0 +1 @@ +The publishable key for your Rownd application. See [App Credentials](/rownd/configuration/app-credentials) \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/web/params/log-level.mdx b/rownd-docusaurus/docs/_snippets/web/params/log-level.mdx new file mode 100644 index 0000000..134d602 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/log-level.mdx @@ -0,0 +1 @@ +Sets the log level for the Rownd Hub. Valid values are `"error"`, `"warn"`, `"info"`, `"debug"`, and `"trace"`. \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/web/params/post-authentication-api.mdx b/rownd-docusaurus/docs/_snippets/web/params/post-authentication-api.mdx new file mode 100644 index 0000000..6190516 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/post-authentication-api.mdx @@ -0,0 +1,29 @@ +Rownd will call this API after an authenticated session is established. This can happen directly after a sign-in, or when the page is reloaded with a currently authenticated user. + + + + The URL that Rownd will call + + + The HTTP method that Rownd will use. Can be either `"post"`, `"put"`, or `"get"`. + + + A map of key-value pairs that Rownd will include in the HTTP headers + + + The HTTP request timeout in milliseconds. If not spescified, it is set to 10000 (10 seconds). + + + +If you specify a `"put"` or `"post"` method, the access token will be included in the request body as a field named `access_token`. For an HTTP `"get"`, it is included in the `Authorization` header. + +There are two properties that Rownd looks for in the response body that drive behavior when thhe API call completes. + + + + A relative path or URL to which Rownd will redirect + + + If `true`, Rownd will refresh the current page + + diff --git a/rownd-docusaurus/docs/_snippets/web/params/post-login-redirect.mdx b/rownd-docusaurus/docs/_snippets/web/params/post-login-redirect.mdx new file mode 100644 index 0000000..1584ce1 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/post-login-redirect.mdx @@ -0,0 +1 @@ +Sets the URL to redirect to after a user signs in. This can be an absolute or relative URL. If not provided, the user will simply remain on the current page. \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/web/params/post-registration-redirect.mdx b/rownd-docusaurus/docs/_snippets/web/params/post-registration-redirect.mdx new file mode 100644 index 0000000..a0b2e2d --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/post-registration-redirect.mdx @@ -0,0 +1,3 @@ +Sets the URL to redirect to after a user signs in for the first time. This can +be an absolute or relative URL. If not provided, the user will simply remain on +the current page. diff --git a/rownd-docusaurus/docs/_snippets/web/params/post-sign-out-api.mdx b/rownd-docusaurus/docs/_snippets/web/params/post-sign-out-api.mdx new file mode 100644 index 0000000..d5d00af --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/post-sign-out-api.mdx @@ -0,0 +1,24 @@ +Rownd will call this API after an authenticated session is terminated by calling `rownd.signOut()`. + + + + The URL that Rownd will call + + + The HTTP method that Rownd will use. Can be either `"post"` or `"put"`. + + + A map of key-value pairs that Rownd will include in the HTTP headers + + + +There are two properties that Rownd looks for in the response body that drive behavior when thhe API call completes. + + + + A relative path or URL to which Rownd will redirect + + + If `true`, Rownd will refresh the current page + + diff --git a/rownd-docusaurus/docs/_snippets/web/params/post-sign-out-callback.mdx b/rownd-docusaurus/docs/_snippets/web/params/post-sign-out-callback.mdx new file mode 100644 index 0000000..eadf9df --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/post-sign-out-callback.mdx @@ -0,0 +1 @@ +Rownd will invoke this function after an authenticated session is terminated by calling `rownd.signOut()`. diff --git a/rownd-docusaurus/docs/_snippets/web/params/post-user-data-update-api.mdx b/rownd-docusaurus/docs/_snippets/web/params/post-user-data-update-api.mdx new file mode 100644 index 0000000..c5c6a64 --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/post-user-data-update-api.mdx @@ -0,0 +1,24 @@ +Rownd will call this API after an event happens that causes the user's profile data to change. Examples of these events include a call to `rownd.user.set()`, `rownd.user.setValue()`, and sign-in completions where data is saved. The new user data will be included in the request body property named `user_data`. + + + + The URL that Rownd will call + + + The HTTP method that Rownd will use. Can be either `"post"` or `"put"`. + + + A map of key-value pairs that Rownd will include in the HTTP headers + + + +There are two properties that Rownd looks for in the response body that drive behavior when thhe API call completes. + + + + A relative path or URL to which Rownd will redirect + + + If `true`, Rownd will refresh the current page + + diff --git a/rownd-docusaurus/docs/_snippets/web/params/root-origin.mdx b/rownd-docusaurus/docs/_snippets/web/params/root-origin.mdx new file mode 100644 index 0000000..83080af --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/params/root-origin.mdx @@ -0,0 +1 @@ +If you're using the same Rownd application across multiple domains (e.g., `rownd.io` and `app.rownd.io`), set this to the "root" _origin_ (e.g., https://rownd.io). \ No newline at end of file diff --git a/rownd-docusaurus/docs/_snippets/web/response-props.mdx b/rownd-docusaurus/docs/_snippets/web/response-props.mdx new file mode 100644 index 0000000..7e121cd --- /dev/null +++ b/rownd-docusaurus/docs/_snippets/web/response-props.mdx @@ -0,0 +1,10 @@ +There are two properties that Rownd looks for in the response body that drive behavior when thhe API call completes. + + + + A relative path or URL to which Rownd will redirect + + + If `true`, Rownd will refresh the current page + + \ No newline at end of file diff --git a/rownd-docusaurus/docs/administration/account.mdx b/rownd-docusaurus/docs/administration/account.mdx new file mode 100644 index 0000000..7d311a2 --- /dev/null +++ b/rownd-docusaurus/docs/administration/account.mdx @@ -0,0 +1,22 @@ +--- +title: "Account" +description: + "Your account is created when you sign into Rownd for the first time." +--- + +Your account information can be found in the "Account and Billing" section of +the platform. This includes your account name, Rownd subscription plan, and +billing information. + +Your account name will be included in the invite email for teammates you invite +to your account. + +We recommend that your account name matches the name of your company or product. + +**Updating your account information** + +1. In the [Rownd platform](https://app.rownd.io) open the top right corner menu under your username. +2. From the menu select **Account and billing.** + +3. In the account and billing page, update your account name in the **Account + name** field, then press **Save**. diff --git a/rownd-docusaurus/docs/administration/images/image.png b/rownd-docusaurus/docs/administration/images/image.png new file mode 100644 index 0000000..b438cb7 Binary files /dev/null and b/rownd-docusaurus/docs/administration/images/image.png differ diff --git a/rownd-docusaurus/docs/administration/teams.mdx b/rownd-docusaurus/docs/administration/teams.mdx new file mode 100644 index 0000000..c702e6e --- /dev/null +++ b/rownd-docusaurus/docs/administration/teams.mdx @@ -0,0 +1,66 @@ +--- +title: "Teams" +description: + "Give team members access to co-manage aspects of your Rownd account." +--- + +#### Inviting new team members + +First, sign into your Rownd account, click on the dropdown menu on the top right +and select **Manage team**. + +![](/images/teams-1.png) + +On the **Team** page, click **Invite team member**. + +![](/images/teams-2.png) + +Enter the new team member's **email** **address** and choose the **level of +access** to grant. There are three different **permission** levels: + +- **Editor:** Can add and edit applicationsbut cannot invite team members or + modify account settings. + +- **Admin:** Full account control over apps, team members, billing, etc. + +- **View-only:** Can view most aspects of the platform but cannot make any + changes. + +![](/images/teams-3.png) + +Click **Save** to send the invitation. Your team member will receive an email +containing a link that will automatically sign them into Rownd and prompt them +to accept or decline the invitation to join your account. + +![](/images/teams-4.png) + +Once the invitation is sent, the new team member will show as **pending** until +they've accepted the invitation. + +![](/images/teams-5.png) + +Once they've accepted the invitation, the pending status will be removed. + +![](/images/teams-6.png) + +#### Editing a team member's access + +Click **Edit** next to the team member whose access you want to modify. + +![](/images/teams-7.png) + +Choose an updated **permission** level for the team member. Then click **save** +to update. + +![](/images/teams-8.png) + +#### Removing a team member + +Click **Delete** next to the team member who you want to remove + +![](/images/teams-9.png) + +On the resulting confirmation dialog, click **Delete** to confirm the action. +The team member will be removed from your account. + +![](/images/teams-10.png) diff --git a/rownd-docusaurus/docs/configuration/app-credentials.mdx b/rownd-docusaurus/docs/configuration/app-credentials.mdx new file mode 100644 index 0000000..df72e08 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/app-credentials.mdx @@ -0,0 +1,42 @@ +--- +title: "App credentials" +description: "Learn how app keys work with Rownd code snippets, SDKs, and APIs." +--- + +When your code interacts with Rownd through an SDK, JavaScript code snippet, or directly with our REST API, you'll need a set of credentials to authenticate your access to the Rownd platform. At Rownd, we call these "app keys" and "app secrets." Every application provides a default app key, but you can create as many additional keys as you need. + +

The app key is a _publishable_ value, meaning it isn't intended to be private. You'll use an app key in all of your user-facing code, such as React or Vue apps, websites, mobile apps, etc.

+ +

Each app key has an associated app secret that will be visible to you only once. App secrets are _private_ values, meaning you should limit the number of people who have access to them. You should also take care to ensure they are not included in publicly visible configuration files, mobile app binaries, website deployments, and so on. They should exist only within your backend server environments or secrets manager.

+ +You can revoke an app key and its associated secret at any time through the [Rownd dashboard](https://app.rownd.io). Be careful, though! Revoking a key that's still in use will likely result in downtime for your app. Ensure you generate new app keys and update your deployments with them before revoking existing keys. + +##### What's the difference? + +**App keys** help identify your application, enable the retrieval of certain application metadata, and initiate authentication from web or mobile. + +**App secrets** authenticate machine-to-machine communication with Rownd to retrieve and update any user profile, generate sign-in (magic) links for any user, and support other more sensitive/restricted functions. + +#### Working with app keys + +From the Rownd dashboard, select the application for which you want to generate an app key, then select **App keys** from the side navigation. + +#### Creating a new app key + +Press the **Add app key** button on the top-right side of the screen. A new app key and secret are generated, then the **Edit app key** dialog is displayed, which contains the name of the app key, the key itself, and its associated secret. + +Be sure to copy and store the app secret in a safe location, since it will be shown only once! Opening the "edit app key" dialog again will show a masked version of the secret. + +You can rename the app key to something that makes sense to you, then press **Save** to save it. + +#### Updating an app key + +1. Click on the three dots beneath the **Action** column on the right side of the app keys table. +2. From the resulting menu, select **Edit** to modify the name of the key (the key and secret are immutable). +3. Make the desired modifications and press **Save** to finish. + +#### Deleting / revoking an app key + +1. Click on the three dots beneath the **Action** column on the right side of the app keys table. +2. Press **Delete** to initiate the deletion process. A confirmation dialog will appear. +3. Press **Delete** within the dialog to permanently revoke the key. It will immediately stop working. \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/applications.mdx b/rownd-docusaurus/docs/configuration/applications.mdx new file mode 100644 index 0000000..561e542 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/applications.mdx @@ -0,0 +1,82 @@ +--- +title: "Applications" + +description: + "Rownd applications connect to your product(s) to provide Rownd authentication + to your users." +--- + +A Rownd application contains a unique code snippet that, when injected across +your product, provides user authentication to your platform. Within your Rownd +application, you can define and customize authentication methods, data types, +and more. You can also connect a Rownd application to your existing tools with +Integrations. It is likely that one Rownd application is enough to span all +aspects of your product, but you can create multiple Rownd apps in your account +as needed. However, a user session cannot span multiple applications. + + +Your application name is used in all verification messages used to authenticate +your users. We recommend using the name of your company or product for your +application name. + + +### Edit an application + +Rownd creates a sample application during initial account setup. You can edit it to suit your needs. + +Modify the name, description, and logo of your existing application from +the **Settings** tab. + +1. On the Settings tab, set the **Application name** and **Application description** as desired. + +2. Drag and drop a logo (PNG or SVG) into the **Application logo** area, or click within it to display a file picker. + +3. Press **Save edits** when finished. + +#### Create a new application + +You may want to create additional applications for separate products or for dev/test environments. + +To create a new application: + +1. Click the application dropdown in the top left corner, and select **Create new + application** from the list. + +2. In the next screen, enter an application name. Optionally, provide a description and logo. + +3. Press **Create**. + +4. Your newly created app will open to its Home tab. + + +#### Switch to another application + +If you have multiple Rownd applications, you can switch between them using the application switcher. + +1. Press the application switcher in the top left corner of the sidebar. + +2. Select a different application from the list of applications. + + +Not seeing the application you're looking for? + +- Try selecting **switch account** in the top right dropdown menu to see if the + application you are looking for is associated with a different account. + +- Are you signed in with the correct user identifier (e.g., email address)? It's possible that the application + you are looking for is associated with an account your current user doesn't have access to. Try signing out and + signing back in with a different email address or social provider. + +#### Delete an application + +If you wish to delete an application, you can delete it from the **Settings** tab. + +1. From the Settings tab, scroll to the bottom and press **Delete application**. + +2. In the modal that appears, confirm you want to delete the app by pressing **Delete**. + + +Deleting your Rownd application completely removes all application data from +Rownd. If the application is being used to authenticate users in your product, +deleting it will prevent any further registrations or authentications. + \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/apple.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/apple.mdx new file mode 100644 index 0000000..fa04854 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/apple.mdx @@ -0,0 +1,35 @@ +--- +title: "Sign in with Apple" +sidebarTitle: "Apple ID" +--- + +Sign in with Apple offers a fast, secure, and privacy-focused method for users to sign in to their accounts on your website and mobile apps. By leveraging the Apple ecosystem, this feature enables users to authenticate using their existing Apple ID without having to create a new account or remember an additional password. + +When enabled, users can take advantage of the strong security and privacy features provided by the Apple platform, including two-factor authentication and email private relay. By offering this sign-in method, you can streamline the authentication process for your users and reduce barriers to entry, resulting in an improved user experience. + +In addition to its ease of use and enhanced security, Sign in with Apple complies with various privacy regulations, helping you maintain compliance and protect your users' data. By providing a trustworthy and user-friendly authentication option, you can attract more users to your platform and foster trust in your services. + + +## Configuring Sign in with Apple + +Using Rownd to add "Sign in with Apple" to your app is quick and easy, usually requiring no code changes. Our implementation supports iOS, Android, and web clients so no matter how your users are accessing your app or service, they can always sign in with their method of choice. + +To enable Sign-in with Apple, complete the following steps. + +#### Configuring Xcode and an Apple Services ID + +1. If you're developing an iOS or macOS app, enable the **Sign in with Apple** capability in Xcode. [See Apple's documentation for more information.](https://developer.apple.com/documentation/xcode/adding-capabilities-to-your-app) +2. Create an [Apple Services ID](https://developer.apple.com/account/resources/identifiers/list/serviceId) for your app. Note the identifier for use in the next step. Ensure that this Callback URL is set within the Services ID: `https://api.rownd.io/hub/auth/apple/callback` + +#### Configuring Rownd + +Now, open your app in the [Rownd platform](https://app.rownd.io/applications). Then click on the **Sign-in methods** tab on the left to adjust your flow. + +![Finding authentication methods is easy; just select "Sign-in methods" from the nav pane.](/images/sign-in-methods-1.png) + +1. Locate the **Sign in with Apple** authentication method and press **Enable**. +2. Enter the Services ID that you created in the previous section. +3. Ensure the **Allow for authentication** switch is turned on. +4. Press **Save.** + +That's it! Your app and/or website is now ready to handle sign-in requests for users with an Apple ID. \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/email.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/email.mdx new file mode 100644 index 0000000..4d994e4 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/email.mdx @@ -0,0 +1,39 @@ +--- +title: "Email sign-in" +sidebarTitle: "Email" +description: "Email-based Authentication with Rownd Sign-in Links offers a secure and user-friendly way for users to access their accounts on your website and mobile apps." +--- + +Email-based authentication using Rownd Sign-in Links provides a secure and user-friendly method for users to sign in to their accounts on your website and mobile apps. With this approach, users don't need to remember complex passwords or create new accounts. Instead, they simply enter their email address and receive a unique sign-in link directly within their inbox, which they can use to securely access their account. + + +**Improve Email Deliverability with Custom Domains** + +Using a custom domain for your authentication emails can significantly improve deliverability rates and enhance your brand's credibility. When your sign-in links come from your own domain instead of a third-party one, email providers are less likely to flag them as suspicious. + +Learn more about setting up [Custom Domains](/configuration/custom-domains/overview) to enhance your authentication experience. + + +This method of authentication is especially convenient for users, as it eliminates the need for password management and reduces the risk of password-related security breaches. By sending a one-time-use sign-in link to the user's email address, you can ensure that only the account owner can access the account. + +Rownd Sign-in Links are designed to be straightforward for both developers and users. Integration is seamless, and the process is intuitive for users, streamlining the authentication experience on your platform. + +Incorporating email-based authentication with Rownd Sign-in Links not only improves the user experience but also enhances the security of your platform, helping you build trust with your users and maintain a secure environment for their data. + +#### Enabling email authentication + +1. Navigate to **Sign-in methods** in the [Rownd dashboard](https://app.rownd.io). +2. Toggle the switch for **Email** to the "on" position. +3. Click **Save**. + +#### Browser Fingerprinting and Reverification for Returning Users + +Rownd uses browser fingerprinting to enhance the sign-in experience for returning users. When a user signs in with email authentication, Rownd securely associates their session with device metadata to form a private, temporary fingerprint. This allows returning users to sign back in—within a configurable time window—without going through the full email verification process again. + +Additionally, Rownd remembers the last sign-in method used. If a user has multiple authentication options, we’ll surface the one they last used to simplify the experience. + +Browser fingerprinting in Rownd is privacy-conscious and session-bound. It doesn’t track users across websites—it simply reduces friction for repeat visits on personal devices. + +#### Customizing email messages + +Rownd allows you to change portions of the email to better match your brand. See our [email customization article](/configuration/customizations/email-customization) for more information. diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/existing-authentication.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/existing-authentication.mdx new file mode 100644 index 0000000..4d22a95 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/existing-authentication.mdx @@ -0,0 +1,8 @@ +--- +title: Validating third-party authenticators +sidebarTitle: Existing authentication +--- + +Rownd's token validator allows you to authenticate a token issued by another authentication provider and exchange it for a Rownd token. This feature is useful when migrating to Rownd from another authentication provider and you want to prevent existing users from being signed-out during the transition. It can also be used when moving between contexts, such as when your code is embedded in an implementation that you don't directly control (e.g., a webview inside someone else's mobile app). + +Use Rownd's [token validator integration](/configuration/integrations/token-validator) to configure this feature. diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/google.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/google.mdx new file mode 100644 index 0000000..018281f --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/google.mdx @@ -0,0 +1,144 @@ +--- +title: "Sign in with Google" +sidebarTitle: "Google" +description: "Turn on the Google authentication method to allow users to sign in with their +Google accounts on your website and mobile apps." +--- + +Sign in with Google is a widely-used, secure authentication method that allows users to quickly sign in to their accounts on your website and mobile apps using their existing Google accounts. By offering this option, you can simplify the authentication process for your users, eliminating the need for them to create a new account or remember an additional password. + +Integrating Sign in with Google streamlines the user experience, as millions of people worldwide already have Google accounts for services like Gmail, Google Drive, and YouTube. By leveraging the familiar Google ecosystem, you can lower the barrier to entry for your platform and potentially increase user engagement. + +In terms of security, Google provides robust measures such as two-factor authentication, helping protect users' accounts from unauthorized access. Furthermore, integrating Sign in with Google can help you comply with various privacy regulations and safeguard your users' data. + +By incorporating Sign in with Google into your authentication options, you can enhance user convenience, improve security, and foster trust in your platform. + + + **New Feature: Google One Tap** + As the name implies, Google One Tap is a streamlined authentication option that allows users to sign in to websites and apps with just one tap on their device if they're already signed-in to a Google account. With One Tap, users can sign in quickly and easily, without having to remember a password, manually enter any credentials, or leave your product. Our customers typically see an instant increase in sign-ups when Google One Tap is enabled. + + +## Prerequisites + +Before you turn on Google Sign-in, you'll need to do a few things in the Google +Cloud Platform. + + +#### OAuth Web Client ID + +Use +[these instructions](https://support.google.com/workspacemigrate/answer/9222992?hl=en) +from Google to create an OAuth web client ID. You'll need this client ID to +configure Rownd for all deployments regardless of web or mobile app. + +The OAuth client ID's **Authorized JavaScript Origins** should contain any sites +on which you will embed Rownd and support Google Sign-in. If you are only using +Rownd on your mobile apps, you can leave this list empty + +#### OAuth iOS Client ID (optional) + +If you are adding Rownd to an iOS app, you'll need to create another OAuth +client ID. In the Google Cloud Platform you can create one just like before, but +this time, set the application type to "iOS". You'll be asked to provide your +app's bundle ID, App Store ID, and team ID. + +When you finish creating the client ID, take note of the **iOS URL Scheme** +value. You will need this later when adding a custom URL scheme to your iOS app. + +This value will be the reversed client ID value and look something like this: + +``` +com.googleusercontent.apps.224565757208-05divavgck1qgqg9b58piodfhqb55h90 +``` + +For detailed instructions check out this +[documentation](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cnative-applications%2Cios) + +#### OAuth Android Client ID (optional) + +If you are adding Rownd to an Android app, you'll need one more OAuth client ID. +Use an existing one or create a new one in the Google Cloud Platform just the +same as before with your web or iOS client ID. When creating, make sure to +select the "Android" application type. Provide your app's package name and SHA-1 +fingerprint. + +For detailed instructions check out this +[documentation](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cnative-applications%2Candroid) + +### Enabling Google Sign-in + +Once you have completed the prerequisites, you can configure Rownd to enable +Google Sign-in. + +1. Navigate to the [Rownd Platform](https://app.rownd.io), and select your +desired application is from the application switcher. +2. Select the **Sign-in methods** option on the left to adjust your flow. + + ![Finding authentication methods is easy; just select "Sign-in methods" from the nav pane.](/images/sign-in-methods-1.png) + +3. Scroll down to view the authentication methods, and click **Enable** next to +**Google**. + +4. On the configuration screen, enter the following information: + + - **Google OAuth Client ID** \- Enter your OAuth web client ID that you created as the first prerequisite step + + - **Google OAuth Client Secret -** Enter the client secret associated with your OAuth web client ID + + - **Google iOS OAuth Client ID** \- Enter your OAuth iOS client ID that you created as a prerequisite + + - **Google OAuth Scopes** \- (Optional) Enter additional OAuth scopes that you would like to request from the user during authentication. By default Rownd will request `email` and `profile`. Most of the time, you don't need to provide a value in this field. + + +If you are using Rownd on an Android app, you do not need to configure your +Android Client ID in the Rownd platform. Google uses the package name and SHA-1 +fingerprint that you provided when creating the OAuth client ID to authenticate +your app. + + +## Enabling Google One Tap +Google One Tap is a streamlined authentication system that allows users to sign in to websites and apps with just one tap on their device. With One Tap, users can sign in quickly and easily, without having to remember a password or manually enter any credentials. One Tap is designed to simplify the sign-in process and improve the user experience, while also providing strong security features such as two-factor authentication and anti-phishing protections. + +### Set up: +1. Pre-requisite: Ensure Google is configured as described above. +2. Click the Google One Tap checkbox +3. If desired, adjust the **Prompt after** field to indicate how long the user should be on the page before being prompted to sign in. This may require some experimentation, since prompting too quickly might be bothersome, while delaying too long might cause the prompt to seem random or out of place. The default of seven seconds works well for many use cases, but your particular website or app may require different settings. +4. Presss **Update**, then press **Save** in the top left corner. + +![Configuring Google One Tap is easy.](/images/google-one-tap.png) + +Google One Tap has a cooldown period that is enforced by Google. If the end-user clicks the close button, the dialog will not appear for between 7 and 60 minutes. When testing this feature, be aware that if intentionally close the Google One Tap dialog, the popup will not appear again until the cooldown period ends. + + + +#### One last thing for iOS Apps + +When Google finishes signing in a user, it calls back into your app on a custom +URL scheme. You'll need to define this inside your XCode project settings. + +1. Click on your project in Xcode, and then select your app under **TARGETS** + +2. Next, go to the **Info** tab and scroll down to the bottom of the view where + you see **URL Types** + +3. Expand **URL Types** and click the **+** icon to add a new value + +4. Set the **URL Schemes** value to the URL Scheme (reversed iOS Client ID) + value that you noted when creating the OAuth iOS client ID earlier. Again, + this value will look something like: + `com.googleusercontent.apps.422565757208-05dqvvigck1qgqg9b58piodfhqb55h90` + +That's it! + + + +Your iOS app with the above changes needs to be published to the App Store _before_ enabling Sign in with Google in the Rownd platform. If you want to enable Sign in with Google on Android and web before your app update has been reviewed by Apple, remove the **iOS Client ID** from the Rownd platform configuration. When your app update goes live, restore the **iOS Client ID** in the Rownd platform. + + + +### Finishing up + +At this point, you're all done! Make sure you save the Google configuration +inside of the Rownd Platform. When you are ready to turn it on, click the toggle +to enable Google Sign-in. Your users will then see a new option in the Rownd +sign-in dialog to continue with Google. diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/guests.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/guests.mdx new file mode 100644 index 0000000..e84ca09 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/guests.mdx @@ -0,0 +1,36 @@ +--- +title: Sign in as guest +sidebarTitle: Guests / Anonymous users +--- + +Authentication should often be a gradual process. Users may not want to provide identifiable information when trying your product for the first time. Or, if your product uses sensitive information like health data, users may not want to link that data to their identity at all. + +For these and other use cases, Rownd offers _guest authentication_, which provides a mechanism for users to onboard your product anonymously—-no email address, phone number, or other contact information is required. + +## How it works +After enabling the **Guests** sign-in method, Rownd will display the option **Continue as guest** in the sign-in modal. Or, if you're writing custom code, you can trigger a guest sign-in automatically on behalf of a visitor who has not yet signed in. + +Rownd doesn't request any identifiers for this user, but simply generates a unique ID for their account. Any profile information that's collected will be associated with this unique ID. + +Traditionally, using a guest account presented difficulty when signing into that same account on other devices or after signing out. To prevent this issue, Rownd supports [Passkeys](./passkeys) so that even anonymous users can sign into their account across multiple devices that have access to the Passkey. + + +Passkeys for guests identify a user only by their random unique identifier. No personal information is associated with a Passkey. + + +### Progressive profiles +Once a user has tried your product, they may feel more confident in sharing personal details in order to preserve their account, receive customer service, and so on. Leveraging [Automations](/configuration/automations/overview), you can prompt these users to add identifiable information at strategic points within a user journey. + +### Detecting guests +While you might allow guests to use certain aspects of your product, you may want to limit their access to specific features. Whether as a means of upselling or because a specific feature relies on identifiable information, you can detect guests in one of two ways. + +1. **Inspect the user's access token:** When a user signs in anonymously, their JWT (access token) is annotated to indicate that they are a guest. The JWT claim looks like this: `https://auth.rownd.io/is_anonymous: true`. + +2. **Inspect the user's profile:** Users who originally signed in as a guest will have an `anonymous_id` field populated within their profile. Check if this is present without any other identifiers like email, phone number, wallet address, etc. + +## Enabling guest sign-in + +1. Navigate to the [Rownd dashboard](https://app.rownd.io/) +2. Select **Sign-in methods** from the sidebar +3. Press **Enable** within the **Guests** sign-in chip. +4. Press **Save** to publish your changes. diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/instant-users.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/instant-users.mdx new file mode 100644 index 0000000..bb30d0e --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/instant-users.mdx @@ -0,0 +1,44 @@ +--- +title: "Instant Users" +sidebarTitle: "Instant Users" +description: "Turn every visitor into a user, instantly" +--- + + +Instant Users captures visitors as users when they land on your website, web app, or mobile app. Are your users seeing the value in your product before they are forced to sign up? With Instant Users, you don't have to worry about this. Our Instant users feature ensures users can explore and experience your app without barriers, making it easier for them to see the value and commit to signing up when they're ready. + + +## Enabling Instant Users +Enabling Instant Users is easy and does not require any additional code. Simply follow the steps below to enable Instant Users for your application. + + +1. Open your app in the [Rownd platform](https://app.rownd.io). Click on the **Settings** tab on the left to adjust your flow and then select the "User Settings" tab. + + + ![Finding the Instant User settings is easy; just select "User Settings" from the nav pane.](/images/instant-users.png). + + +2. Toggle on "Instant Users" and the cleanup timeline. This is how long of inactivity before instant users are "cleaned up". Every use-case is different and our default i 30 days. + +3. To confirm your changes, press **Save** in the upper right-hand corner of the page. + + +## The User Spectrum +Instant users is the first step along the Rownd User Spectrum. An instant user gets granted a JWT, that JWT has a normal lifecycle and security, and the goal is to show your user enough of your app and get them comfortable aenough to either login as a guest, enter a piece of verifiable data, or login with a verifiable email or phone number (either manually or through a social sign-in) + + +### The Spectrum: + + +1. **Instant user**: Upon initial visit, a new visitor receives a user ID as they move through your app, starting as a partial profile. + + +2. **Guest user**: Visitors can continue as guests, maintaining progress and exploring your app without immediate sign-up. + + +3. **Unverified user**: Users can provide an email without verification, reducing friction and allowing continued app use. + + +4. **Verified user**: Eventually, users provide verifiable information, like an email or Google account, to fully sign up and re-access their account. + + ![The Spectrum of user authentication is broad](/images/lightmode-demo-3uhCS-zi.svg). \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/oauth.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/oauth.mdx new file mode 100644 index 0000000..e0a8315 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/oauth.mdx @@ -0,0 +1,42 @@ +--- +title: 'OpenID Connect (OIDC) and OAuth2' +sidebarTitle: 'OpenID / OAuth2' +description: 'Leverage existing OAuth-compliant identity providers' +--- + +While Rownd provides a superior authentication experience for most users, there may be occasions where end-users need to authenticate with a third-party system. + +This can be especially important when dealing with corporate SSO requirements. CISO policy may require that all users sign in through an in-house identity provider or an enterprise cloud provider like Microsoft or Google. (If you're looking for Google authentication, we highly recommend using our [built-in Google authentication method.](./google)) + +Follow the steps below to configure Rownd to interoperate with your target OpenID or OAuth2 server. + +If you require a SAML authentication flow, please [get in touch](mailto:support@rownd.io). + +## Supported flows + +Rownd supports the following authentication flows: +- Authorization code flow +- Authorization code flow with proof key for code exchange (PKCE) +- Authorization code flow with JWT-secured authorization requests + +## Configuring an OpenID or OAuth2 client + +Before getting started, be sure you obtain a valid client ID and--if required--client secret or private key from your OAuth provider. + +1. From the [Rownd platform](https://app.rownd.io), navigate to the **Sign-in methods** sidebar tab. +2. In the *Additional sign-in methods* section, select **Enable additional methods**. +3. From the *Add additional sign-in methods* dialog, locate the **Custom** option and select **Add**. +4. Enter a name for the authentication method (e.g., My SSO provider) and optionally upload light and dark mode icons that will represent this authentication method. +5. Select the type of authentication flow: OpenID or OAuth2. +6. *(Required for OpenID)* Provide the issuer's base URL which hosts the `/.well-known/openid-configuration` endpoint (e.g., `https://auth.mycorp.com`). +7. Provide the default scopes that should be included in every authentication request. You can conditionally include additional scopes at authentication time. +8. Click **Next** to continue to the next step. +9. Enter your **Client ID** +10. If applicable, select the type of *client authentication* your provider requires and then paste the authentication secret in the provided input. +11. *(OAuth2 only)* Provide applicable values for the various authorization server endpoints (e.g., authorization endpoint, token endpoint, JWK endpoint, etc). +12. Press **Enable** at the bottom of the dialog to add the sign-in method to your available authentication options. The dialog will close. +13. Press **Save** at the top-right of the window to persist your changes. + +## Need something else? + +If you require assistance setting up a custom authentication provider or need an option not currently covered, please [contact us](mailto:support@rownd.io). diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/overview.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/overview.mdx new file mode 100644 index 0000000..bcee57c --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/overview.mdx @@ -0,0 +1,113 @@ +--- +title: "Authentication methods" +sidebarTitle: "Overview" +description: + "Configure what sign-in methods are used in your app and websites" +--- + +Authentication should not be a tax on your growth. With Rownd's adaptive authenication and wide range of authentication options, we help maximize both product flexibility and increase user growth. + +## Navigating to authentication methods + +Open your app in the [Rownd platform](https://app.rownd.io/applications). Then click on the **Sign-in methods** tab on the left to adjust your flow. + +![Finding authentication methods is easy; just select "Sign-in methods" from the nav pane.](/images/Sign-in-methods-page.png) + +## Available authentication methods + +You can use any combination of the following authentication methods: + + + + Passwordless sign-in with a passkey (biometrics) + + + Passwordless email sign-in + + + One tap sign-in with a Google account + + + Fast sign-in with Apple ID + + + Passwordless SMS-based sign-in + + + Anonymous sign-in for unidentified users + + + When detected, sign in using Metamask, Coinbase, etc. + + + Get in touch to discuss your needs! + + + +## Adaptive sign-in with Rownd + +Rownd's adaptive sign-in feature offers a tailored authentication experience for users by adapting the sign-in method depending on the user's device. This versatile approach ensures the most convenient and secure authentication option is presented, enhancing the user experience and promoting increased user engagement. + +### Device-specific sign-in methods + +Rownd's adaptive sign-in can detect the user's device and adjust the available authentication options accordingly. This ensures that the user is presented with the most appropriate sign-in method for their device, resulting in a seamless and intuitive experience. Some device-specific sign-in methods include: + +- **Biometric authentication:** Rownd utilizes passkey technology to automatically utilize whatever biometric featuers a device has. For devices with biometric capabilities, such as fingerprint or facial recognition, Rownd can offer these secure and convenient methods as authentication options. +- **Device-based authentication:** For users with device-specific accounts (e.g., Apple ID or Google accounts), Rownd can present the option to sign in using these platform-specific accounts. +- **SMS or email authentication:** For devices without biometric or device-based options, Rownd can provide authentication via SMS or email, sending a unique, one-time-use login link to the user's mobile device or email address. + +### Customizing sign in methods by device on the Rownd platform +1. **Navigate to the Sign in methods tab:** After installing Rownd with a code snippet or SDK, navigate to the sign in methods tab in the Rownd Platform. +![Check out the sign in methods tab.](/images/Sign-in-methods-page.png) +2. **Configure [mobile app settings](/configuration/mobile/overview):** If you have a mobile app, configure your Google, Apple and mobile settings to get started. This will ensure proper deep linking to your mobile apps with your new customizations. +![Configure mobile app settings](/images/Mobile-app-settings2.png) +3. **Customize sign in method orders by device:** Select the device type at the top (Desktop, iOS, Android), drag, drop, prioritize, and hide methods until you’re liking your customizations for each device type. We recommend prioritizing Apple sign in on iOS devices and prioritizing Google sign in on Android devices. +![Customize the order and visability by device.](/images/iOS-customize-sign-in-method.png) +4. **Test it out:** Save and try out your new customizations in your app! Continue to iterate based on on the way your users are signing in. + +
+ +
+ +### Benefits of adaptive sign-in + +Implementing Rownd's adaptive sign-in feature in your mobile app provides several advantages: + +1. **Improved user experience:** By offering device-specific sign-in methods, you can cater to users' preferences and provide a more convenient and intuitive authentication process. +2. **Increased security:** Adaptive sign-in ensures that the most secure method available on the user's device is presented, helping to safeguard user accounts and protect sensitive data. +3. **Higher engagement and retention:** A tailored authentication experience can lead to higher user engagement and retention, as users are more likely to continue using an app that offers a seamless and convenient sign-in process. + +## Unverified Users + + + +See more details on [Unverified Users](/configuration/authentication-methods/unverified) \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/passkeys.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/passkeys.mdx new file mode 100644 index 0000000..b6e631b --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/passkeys.mdx @@ -0,0 +1,48 @@ +--- +title: "Sign in with Passkeys" +sidebarTitle: "Passkeys" +description: "Enable passkey authentication to provide a secure and seamless sign-in experience for users with passkey-enabled devices." +--- + +Passkeys offer a secure and convenient method for users to sign in to their accounts on your website and mobile apps. By enabling passkeys, users with passkey-enabled devices can save their passkeys to their account. Once a passkey is saved, users can quickly sign in using their passkeys, providing a seamless and efficient experience. + +## Enabling passkeys +Enabling passkeys is easy and does not require any additional code. Simply follow the steps below to enable passkeys for your application. + +1. Open your app in the [Rownd platform](https://app.rownd.io/applications). Then click on the **Sign-in methods** tab on the left to adjust your flow. + + ![Finding authentication methods is easy; just select "Sign-in methods" from the nav pane.](/images/sign-in-methods-1.png) + +2. Scroll down to view the authentication methods, and press **Enable** next to **Passkeys**. + + ![Configuring passkeys only takes a few seconds.](/images/passkey-config.png) + + + At this time, passkey cannot be the only form of sign-in enabled. Users can add passkeys after signing up with + another method. After the first sign-in, they can use their passkeys to sign in to their account. This ensures + account access across different devices. + + +3. To confirm your changes, press **Save** in the upper right-hand corner of the page. + +With passkeys enabled, users with passkey-enabled devices can now enjoy a seamless and secure sign-in experience on your website and mobile apps. + + + + 1. Configure iOS "Mobile app settings" in the [Rownd Platform](https://app.rownd.io/methods) with a subdomain, bundle ID, and a team ID. Instructions can be found [here](/configuration/mobile/ios). + 2. In Xcode ensure "Associated Domains" for applinks and webcredentials are configured with your Rownd subdomain + +applinks:your_set_subdomain.rownd.link + +webcredentials:your_set_subdomain.rownd.link + +See image below + + +![Apple XCode view.](/images/applinks.png) + + + + 1. Configure iOS "Mobile app settings" in the [Rownd Platform](https://app.rownd.io/methods) with a subdomain, package name, and a SHA 256 cert fingerprint. Instructions can be found [here](/configuration/mobile/android). + + diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/phone-sms.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/phone-sms.mdx new file mode 100644 index 0000000..5b4077f --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/phone-sms.mdx @@ -0,0 +1,41 @@ +--- +title: "Sign in with SMS / Phone Number" +sidebarTitle: "Phone / SMS" +description: "Passwordless SMS authentication" +--- + +SMS-based authentication using Rownd Sign-in Links is a secure and convenient method for users to sign in to their accounts on your website and mobile apps. This approach eliminates the need for passwords, instead sending a unique, one-time-use sign-in link directly to users' mobile devices via SMS. By simply clicking on the link, users can securely access their accounts without having to remember any passwords. + + +**Enhance SMS Link Trust with Custom Domains** + +Using a custom domain for your SMS authentication links can significantly improve user trust and click-through rates. When users receive links that contain your own domain rather than a generic one, they're more likely to perceive them as legitimate and click through. + +Learn more about setting up [Custom Domains](/configuration/custom-domains/overview) to create a more cohesive branded experience. + + +This authentication method offers several advantages, including ease of use for users and enhanced security. By leveraging users' mobile devices for authentication, you can reduce the risk of password-related security breaches and ensure that only the authorized account holder has access to the account. + +Integrating SMS-based authentication with Rownd Sign-in Links is straightforward for developers, and the process is intuitive for users. This results in a streamlined authentication experience on your platform and a reduced barrier to entry for your users. + +By incorporating SMS-based authentication with Rownd Sign-in Links, you can offer a user-friendly and secure authentication option that promotes trust in your platform and safeguards user data. + +#### When to use phone sign-in + +There are few more powerful ways to bridge the computer-to-mobile gap than with SMS sign-in. Rownd utilizes powerful sign-up links that make it easy to verify a phone number without having to copy down annoying 4-8 digit passcodes. + +When paired with Rownd's mobile download links, users can leverage SMS to download and sign-in to your mobile app in just a few taps. + +#### Enabling SMS authentication + +1. Navigate to **Sign-in methods** in the [Rownd dashboard](https://app.rownd.io). +2. Toggle the switch for **Phone number** to the "on" position. +3. Click **Save**. + + +There is an incremental cost to send SMS text messages. Most Rownd plans include a set number of messages per-month and a small surcharge for each message thereafter. Surcharges may vary based on the destination country / carrier. + + + +SMS is disabled for free accounts by default. [Get in touch](https://rownd.io/contact) with us if you'd like to enable it. + \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/authentication-methods/unverified.mdx b/rownd-docusaurus/docs/configuration/authentication-methods/unverified.mdx new file mode 100644 index 0000000..c524c04 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/authentication-methods/unverified.mdx @@ -0,0 +1,53 @@ +--- +title: "Unverified Users" +sidebarTitle: "Unverified Users" +description: "Allow first-time users to sign up without immediate verification. On subsequent visits, they will be prompted to verify their email or phone number." +--- + + + +## Enabling Delayed Verification for unverified Users + +Enabling delayed verification for unverified users allows first-time users to sign up without needing to verify their email immediately. This feature reduces friction during the sign-up process, providing a smoother user experience, especially for new users. + +On the user’s second visit, they will be prompted to verify their account to continue accessing the app. This ensures that your app maintains security while allowing users to try it out with minimal barriers. + +This feature is particularly useful for applications where quick sign-up is critical, and you want to prioritize user experience without compromising security for returning users. + +### Benefits of Delayed Verification +- **Lower Friction:** First-time users can sign up quickly without needing to verify their email immediately. +- **User Experience:** Reduces the likelihood of sign-up abandonment by making the process faster and more seamless. +- **Improved Security:** Users will still be required to verify their account on subsequent visits, ensuring that only legitimate users can access the app long-term. +- **Flexible Integration:** Does not require any additional code beyond enabling the setting on your Rownd platform. + +### Enabling Delayed Verification + +Enabling delayed verification for unverified users is simple and does not require coding changes. Just follow the steps below: + +1. **Open your application in Rownd** + Open your app in the [Rownd platform](https://app.rownd.io/applications). In the left-hand navigation panel, click on the **Settings** tab and navigate to the **User Settings** tab. + +2. **Enable Delayed Verification** + Scroll down to the part of the page where you'll find the toggle next to **Allow delayed verification**. Flip the toggle to enable the feature for your application. + +3. **Save Changes** + After enabling delayed verification, click **Save** in the upper right-hand corner to confirm your changes. + + +### How It Works for Users +Once enabled, users can sign up without immediate verification by entering their email in the email sign-in field if enabled. They will be able to access the app and use its features, but when they return to the app on a later visit, they will be prompted to verify their email to continue using the app. + +For users who have a recognized device (via browser fingerprinting), the verification prompt may be skipped on future visits as long as the device is recognized. + +### Use Cases +- **E-commerce apps**: Users can quickly browse and explore products without immediate verification but will need to verify their account for checkout. +- **Social apps**: New users can sign up and explore the app, and on their second visit, they can verify their email or phone for account recovery and security. +- **Service-based apps**: Let users try out basic features first without verification, and later require verification for accessing premium or restricted features. + +### Next Steps + +Once delayed verification is enabled, consider reviewing your sign-in flows and customizing the user experience even further. Rownd’s platform offers additional customization options, such as customizing the verification prompt and setting different requirements for different user groups. + +--- + +If you have any further questions about this feature or need help with troubleshooting, feel free to reach out to Rownd’s support team at support@rownd.io diff --git a/rownd-docusaurus/docs/configuration/automations/overview.mdx b/rownd-docusaurus/docs/configuration/automations/overview.mdx new file mode 100644 index 0000000..5bd70ad --- /dev/null +++ b/rownd-docusaurus/docs/configuration/automations/overview.mdx @@ -0,0 +1,51 @@ +--- +title: "Automations Overview" +sidebarTitle: "Overview" +description: + "Streamline your sign up experience with Rownd automaitions." +--- + +#### What are automations? + +In Rownd, Automations are tools that empower you to enhance and optimize your app's sign-up process without any coding. You can configure automations to add functions to your app like prompting users to sign in, collecting additional information, or triggering specific Rownd actions when users interact with certain elements. Automations help improve your app's sign in and user flows without the need for extensive technical expertise. + + +Note: Rownd must be installed on your app in order for automations to work properly. + + +![The automations catalog.](/images/automation-catalog.png) + +#### Why use automations? + +- **Fast iteration and testing**: With Automations, you can experiment with new elements in your sign-up flow and iterate rapidly. +- **No-code server side changes**: Rownd operates server-side, ensuring that your changes and Automations are instantly applied to your app when you save them on the platform. There's no need to involve engineering for minor adjustments or updates. +- **Easy customization**: One significant advantage of Automations is the ability to tailor the wording and style for each one. For instance, you can easily adjust the title of a sign-in prompt to better match your content. + + +#### How It Works + +1. Browse the Automations catalog in the Automations tab and select the automation that best matches what you are trying to do. +2. Configure your automation, including naming it and specifying the type of prompt it will be, among other options. +3. Customize the style and wording of your automation, which may vary depending on the type. +4. Save and publish to immediately implement your automation in your app. +5. Iterate over time by making adjustments and refinements until your automation operates optimally for you users. + +#### Current and coming soon Rownd automations + +While this feature is still in Beta, we are still building new automations every week! Below are a few of our existing and in progress automations and what they will help you accomplish. + +* **Sign-In Prompt**: Encourage users to sign in based on clicks, time duration, sessions, or an entire page. Connect this prompt to a sign-in button or an app feature requiring authentication. + +* **Sign-Out Event**: Enable users to end their current session with a "Sign-out" button or any other element you choose. + +* **Request Additional Information**: Enable this automation to easily gather extra user information. Once activated, it prompts users to provide additional details, making it applicable in various scenarios such as age verification, collecting usernames, and requesting secondary email or address information. + +* **Collect Form Data (Coming Soon!)**: Connect Rownd data fields to a form in your application to passively add information to a user's Rownd profile while they use your app. + +* **Open Profile (Coming Soon!)**: Launch the Rownd profile from a button or element within your app, allowing users to update their data and connected accounts. + +* **Google One Tap (Coming Soon!)**: Prompt users to sign in using a Google account. Configure when this prompt appears, whether on click, based on time, session, or an entire page. Use it to re-prompt users if they initially ignore the one-tap prompt. + +* **Passkey prompt (Coming Soon!)** The passkey prompt automation allows you to prompt users to add a passkey to their account based on clicks, time duration, sessions, or an entire page. You can connect this prompt to a button or element within your app to prompt users to add a passkey. + +* **Promotional Opt in (Coming Soon!)**: This automation enables you to request email or text message marketing opt-ins from your users with ease. When enabled, you can customize and automate the opt-in process according to your preferences. You have the flexibility to determine the frequency, timing, and mode of communication that works best for your users. diff --git a/rownd-docusaurus/docs/configuration/automations/sign-in-prompt.mdx b/rownd-docusaurus/docs/configuration/automations/sign-in-prompt.mdx new file mode 100644 index 0000000..ec15840 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/automations/sign-in-prompt.mdx @@ -0,0 +1,70 @@ +--- +title: "Sign in prompts" +description: + "Encourage user sign in with customized prompts." +--- + +The sign in prompt automation allows you to encourage users to sign in based on clicks, time duration, sessions, or an entire page. Connect this prompt to a sign-in button or an app feature requiring authentication. + +#### Sign in prompt use cases + +* **Content Gating**: Enhance user engagement by implementing click-triggered sign-in prompts within your application. These prompts allow users to explore your app freely, only requesting sign-in when specific elements are clicked. For example, if you wish to restrict access to certain features for unauthenticated users, seamlessly integrate a Rownd sign-in prompt to the corresponding tab or element in your app. This process takes just minutes to implement, encouraging users to sign in to access exclusive content. + +* **Free Trials**: Provide prospective users with the opportunity to experience your product through free trials without the initial sign-up requirement. Utilize time-based sign-in prompts to prompt users to sign in after a defined period, whether it's 5 minutes, 24 hours, or 4 days—flexibility tailored to your needs. Time-based prompts allow users ample time to familiarize themselves with your product, generating excitement and increasing the likelihood of conversion when prompted to sign up. + +* **Simple Buttons**: Simplify the process of integrating sign-in functionality into your website, even when your development team has limited availability. Sign-in prompts empower you to connect sign-in actions to any button or element seamlessly. Additionally, you can redirect users to specific destinations after they sign in, providing complete control over their post-login journey. + + +#### How does it work? + +1. **Create a New Sign-In Prompt Automation** + + Begin by adding a new Sign-In Prompt Automation from the "Automations" tab. + + ![The automations catalog.](/images/automation-catalog.png) + +2. **Configure Your Automation** + + Tailor your automation to fit your use case. Determine the type of prompt you require, whether it's click-triggered, time-based, page-scoped, or immediately after sign-in. Define any specific requirements and redirect links. + + ![Configure step.](/images/automation-configure1.png) + + For click-triggered prompts on websites and web apps, you'll need to provide an element selector to connect to your Rownd automation. Refer to the video below for guidance on finding and copying an element selector. + + +
+ +
+ +3. **Customize Your Prompt** + + Personalize your prompt by adjusting the wording and content that will be displayed to your users for this particular prompt. + + ![Customization step.](/images/automation-customize.png) + +4. **Finish creating Your Automation** + + Once you've configured and customized your prompt, click 'Create' to officially add your new automation to your app. + + ![Once you've created your automation, it will appear in your automations table.](/images/automation-add-success.png) + +5. **Ongoing Optimization** + + Continuously refine, modify, and iterate on your automations to align with user behaviors and preferences. + + + + + +Automations are currently a Beta feature, and we highly value user feedback. Please feel free to share your feedback and ideas with us by sending an email to support@rownd.io. + + + + diff --git a/rownd-docusaurus/docs/configuration/cross-domain/implementation.mdx b/rownd-docusaurus/docs/configuration/cross-domain/implementation.mdx new file mode 100644 index 0000000..ab18ac6 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/cross-domain/implementation.mdx @@ -0,0 +1,70 @@ +--- +title: 'Implementation' +description: 'Get cross-domain authentication added to your product' +--- + +## Getting Started + +1. **Locate your subdomain from the Rownd dashboard's** [settings](/configuration/mobile) + +2. **Create or use an existing** [**app key**](/configuration/app-credentials) + +3. **Form your root origin URL using the following template** + ``` + https://REPLACE_WITH_YOUR_SUBDOMAIN.rownd.link/root/ + ``` + +4. Add the root origin URL to your implementation of the Rownd SDK (see [examples](#implementation-examples) below) + +5. Test to ensure everything is working. You should be able to visit one of your domains, sign in successfully, and then visit another of your domains and remain signed in. + +### Implementation Examples + +If you're using our WordPress, Shopify, or similar integrations, look for a "Root Origin URL" setting the the plugin or app's configuration page. + +Below are some examples of how to enable cross-origin authentication across various Rownd SDKs. + +#### Next.js / React / Remix + +```jsx +return ( + + + + + {children} + + + +); +``` + +#### JavaScript + +For websites using the standard snippet: + +```javascript +_rphConfig.push(['setRootOrigin', yourRootOriginUrl]); +``` + +## Best Practices + +1. Maintain consistent configuration across all properties + +2. Use trusted SSL certificates for all domains + +3. Test authentication flow in development environment before implementing in production + +4. Test user flows across different domains + +## Troubleshooting + +If the authentication state isn't syncing, make sure you: + +1. Verify that the root origin configuration is the same across all web properties + +2. Be sure SSL certificates are valid + +3. Confirm the app key is correct + +If you're still facing difficulty, please reach out to [Rownd support](mailto:support@rownd.io?subject=Cross-domain%20auth%20not%20working). diff --git a/rownd-docusaurus/docs/configuration/cross-domain/overview.mdx b/rownd-docusaurus/docs/configuration/cross-domain/overview.mdx new file mode 100644 index 0000000..1f2609b --- /dev/null +++ b/rownd-docusaurus/docs/configuration/cross-domain/overview.mdx @@ -0,0 +1,75 @@ +--- +title: "Adding cross-domain authentication" +sidebarTitle: "Overview" +description: "Keep users signed in across all of your web properties" +--- + +Rownd's cross-domain authentication provides a seamless user experience across multiple domains and subdomains without third-party cookies. This modern approach maintains secure user sessions across your entire digital ecosystem. + +## How It Works + +Rownd uses a novel authentication method that: + +* Operates independently of third-party cookies + +* Maintains sessions across different domains + +* Synchronizes user state automatically + +* Preserves security while improving user experience + +## Benefits + +* **Seamless User Experience**: Users stay signed in across all your properties + +* **Cookie-Independent**: Future-proof against browser privacy changes + +* **Flexible Implementation**: Works across web apps, mobile apps, and websites + +* **Improved Conversion**: Reduces friction in user journeys + +* **Enhanced Security**: Maintains secure sessions without compromising user privacy + +## Common Use Cases + +### Landing Page to Application + +1. Add Rownd to your marketing site + +2. Enable passive authentication (e.g., Google One Tap) + +3. Users automatically sign in when accessing your main application + +4. Increases conversion by removing authentication barriers + +### Documentation Portal Integration + +1. Implement Rownd across your documentation site + +2. Provide personalized help based on user context + +3. Track documentation usage patterns + +4. Deliver customized content based on user preferences + +### Multi-App Ecosystem + +1. Deploy Rownd across multiple applications + +2. Maintain consistent authentication state + +3. Works seamlessly with [sub-brands](https://docs.rownd.io/configuration/customizations/sub-brands) + +4. Create branded experiences for different user segments + +To implement cross-domain authentication within your product, follow our[ implementation steps.](/configuration/cross-domain/implementation) + +## SDK References + +For detailed implementation guidelines, refer to: + +* [Web SDK Documentation](https://docs.rownd.io/sdk-reference/web) + +* [Mobile SDK Documentation](https://docs.rownd.io/sdk-reference/mobile) + +* [Sub-brands Configuration](https://docs.rownd.io/configuration/customizations/sub-brands) diff --git a/rownd-docusaurus/docs/configuration/custom-domains/active-custom-domain.png b/rownd-docusaurus/docs/configuration/custom-domains/active-custom-domain.png new file mode 100644 index 0000000..c1ccc6c Binary files /dev/null and b/rownd-docusaurus/docs/configuration/custom-domains/active-custom-domain.png differ diff --git a/rownd-docusaurus/docs/configuration/custom-domains/cloudflare-example.png b/rownd-docusaurus/docs/configuration/custom-domains/cloudflare-example.png new file mode 100644 index 0000000..4ad642a Binary files /dev/null and b/rownd-docusaurus/docs/configuration/custom-domains/cloudflare-example.png differ diff --git a/rownd-docusaurus/docs/configuration/custom-domains/dns-records.mdx b/rownd-docusaurus/docs/configuration/custom-domains/dns-records.mdx new file mode 100644 index 0000000..1a5df01 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/custom-domains/dns-records.mdx @@ -0,0 +1,289 @@ +--- +title: "How to set custom domains in DNS providers" +sidebarTitle: "DNS Provider Steps" + +--- +These docs shows how to add the **CNAME** and **TXT** records required to configure a custom authentication domain (e.g., for magic‑link emails, smart links, etc.) with Rownd. Each example uses: + +- **CNAME**: points `` to your Rownd subdomain (``). +- **TXT**: creates a verification record at `` with the token ``. + +Click the links for your DNS provider’s official docs for more details. + +--- + +## Table of Contents + +1. [Cloudflare](#1-cloudflare) +2. [GoDaddy](#2-godaddy) +3. [Google Cloud DNS](#3-google-cloud-dns) +4. [AWS Route 53](#4-aws-route-53) +5. [Azure DNS](#5-azure-dns) +6. [Namecheap](#6-namecheap) +7. [DigitalOcean DNS](#7-digitalocean-dns) +8. [Hover](#8-hover) +9. [DNS Made Easy](#9-dns-made-easy) +10. [Dyn Managed DNS](#10-dyn-managed-dns) +11. [Squarespace](#11-squarespace) + +--- + +## 1. Cloudflare + +- **Official Docs**: [Manage DNS Records – Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/) + +### Add a CNAME Record + +| Field | Value | +|--------|--------------------------------| +| Type | CNAME | +| Name | `` | +| Target | `` | +| TTL | Auto (or your preferred value) | + +### Add a TXT Record + +| Field | Value | +|---------|-------------------------------| +| Type | TXT | +| Name | `` | +| Content | `` | +| TTL | Auto (or your preferred value)| + +--- + +## 2. GoDaddy + +- **Official Docs**: + - [Add CNAME Records](https://support.godaddy.com/help/add-cname-records-19238) + - [Add TXT Records](https://support.godaddy.com/help/add-a-txt-record-19236) + +### Add a CNAME Record + +| Field | Value | +|------------|-------------------------| +| Type | CNAME | +| Host | `` | +| Points to | `` | +| TTL | 600 sec (or default) | + +### Add a TXT Record + +| Field | Value | +|-----------|-------------------------------| +| Type | TXT | +| Host | `` | +| TXT Value | `` | +| TTL | 600 sec (or default) | + +--- + +## 3. Google Cloud DNS + +- **Official Docs**: [Resource Record Types – Cloud DNS](https://cloud.google.com/dns/docs/records) + +### Add a CNAME Record + +| Field | Value | +|----------------------|----------------------------| +| DNS Name | `.` | +| Resource Record Type | CNAME | +| Canonical name | `.` | +| TTL | 300 sec (or your preference)| + +### Add a TXT Record + +| Field | Value | +|----------------------|--------------------------------| +| DNS Name | `` | +| Resource Record Type | TXT | +| TTL | 300 sec (or your preference) | +| TXT data | `""` | + +--- + +## 4. AWS Route 53 + +- **Official Docs**: [Creating Records – Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html) + +### Add a CNAME Record + +| Field | Value | +|-------------|-------------------------| +| Record name | `` | +| Record type | CNAME | +| Value | `` | +| TTL (sec) | 300 | + +### Add a TXT Record + +| Field | Value | +|-------------|--------------------------------| +| Record name | `` | +| Record type | TXT | +| Value | `""` | +| TTL (sec) | 300 | + +--- + +## 5. Azure DNS + +- **Official Docs**: [Add Records to DNS Zones – Azure DNS](https://learn.microsoft.com/azure/dns/dns-zones-records) + +### Add a CNAME Record + +| Field | Value | +|-------|-------------------------| +| Name | `` | +| Type | CNAME | +| Alias | `` | +| TTL | 3600 sec | + +### Add a TXT Record + +| Field | Value | +|---------|-------------------------| +| Name | `` | +| Type | TXT | +| Value | `` | +| TTL | 3600 sec | + +--- + +## 6. Namecheap + +- **Official Docs**: [How to Add DNS Records – Namecheap](https://www.namecheap.com/support/knowledgebase/article.aspx/9756/2237/how-to-add-dns-records-for-a-domain) + +### Add a CNAME Record + +| Field | Value | +|-------|-------------------------| +| Type | CNAME | +| Host | `` | +| Value | `` | +| TTL | Automatic | + +### Add a TXT Record + +| Field | Value | +|-------|-------------------------| +| Type | TXT | +| Host | `` | +| Value | `` | +| TTL | Automatic | + +--- + +## 7. DigitalOcean DNS + +- **Official Docs**: [Add DNS Records – DigitalOcean](https://docs.digitalocean.com/products/networking/dns/how-to/add-records/) + +### Add a CNAME Record + +| Field | Value | +|-------------|-------------------------| +| Host name | `` | +| Will direct to | `` | +| Record type | CNAME | + +### Add a TXT Record + +| Field | Value | +|--------|-------------------------| +| Host | `` | +| Value | `` | +| Type | TXT | + +--- + +## 8. Hover + +- **Official Docs**: [Adding a DNS Record – Hover Help](https://help.hover.com/hc/en-us/articles/203729334-Adding-a-DNS-record) + +### Add a CNAME Record + +| Field | Value | +|------------|-------------------------| +| Type | CNAME | +| Host name | `` | +| Points to | `` | + +### Add a TXT Record + +| Field | Value | +|-----------|-------------------------| +| Type | TXT | +| Host name | `` | +| Value | `` | + +--- + +## 9. DNS Made Easy + +- **Official Docs**: [Adding Records – DNS Made Easy](https://support.dnsmadeeasy.com/hc/en-us/articles/115005531225-Adding-Records) + +### Add a CNAME Record + +| Field | Value | +|-------|-------------------------| +| Type | CNAME | +| Host | `` | +| Value | `` | + +### Add a TXT Record + +| Field | Value | +|-------|-------------------------| +| Type | TXT | +| Host | `` | +| Value | `` | + +--- + +## 10. Dyn Managed DNS + +- **Official Docs**: [Using the DNS Manager – Dyn](https://help.dyn.com/using-dns-manager/) + +### Add a CNAME Record + +| Field | Value | +|----------|-------------------------| +| Type | CNAME | +| Hostname | `` | +| Target | `` | + +### Add a TXT Record + +| Field | Value | +|----------|-------------------------| +| Type | TXT | +| Hostname | `` | +| TXT Data | `` | + +--- + +## 11. Squarespace + +- **Official Docs**: + - [Adding DNS records to your domain – Squarespace](https://support.squarespace.com/hc/en-us/articles/360002101888-Adding-DNS-records-to-your-domain) + - [DNS records for connecting third-party domains – Squarespace](https://support.squarespace.com/hc/en-us/articles/360035485391-DNS-records-for-connecting-third-party-domains) + +### Add a CNAME Record + +| Field | Value | +|-------|-------------------------| +| Type | CNAME | +| Host | `` | +| Data | `` | + +### Add a TXT Record + +| Field | Value | +|-------|-------------------------| +| Type | TXT | +| Host | `` | +| Data | `` | + +--- + +Follow these steps to configure your custom authentication domain for Rownd smart links and magic‑link flows. diff --git a/rownd-docusaurus/docs/configuration/custom-domains/overview.mdx b/rownd-docusaurus/docs/configuration/custom-domains/overview.mdx new file mode 100644 index 0000000..4d301ff --- /dev/null +++ b/rownd-docusaurus/docs/configuration/custom-domains/overview.mdx @@ -0,0 +1,112 @@ +--- +title: "Custom Domain Configuration" +sidebarTitle: "Custom Domains" + +--- +Custom domains allow you to maintain a consistent brand experience throughout your users' authentication journey. By configuring a custom domain, all authentication flows, magic links, and auth-related emails will use your domain instead of Rownd's default domains. + +## Benefits of Custom Domains + +- **Enhanced Brand Trust**: Users see only your domain throughout the entire authentication process +- **Improved Deliverability**: Email providers often trust established domains more than third-party services +- **Consistent User Experience**: Seamless transitions between your application and authentication flows +- **HIPAA and Compliance**: Help meet regulatory requirements for sensitive industries + +## Setting Up Custom Domains + +### Step 1: Access Domain Settings + +Navigate to the Settings section in the left sidebar of your Rownd dashboard. + +![Access Settings in the left navigation](settings-custom-domains.png) + +### Step 2: Add Your Custom Domain + +Under the "Primary authentication domain" section, you'll see your current authentication domain. To add a custom domain: + +1. Type your domain (e.g., auth.acme.com) +2. The domain will show as "Pending" until verified + +![Add your custom domain for verification](verification-custom-domains.png) + +### Step 3: Configure DNS Records + +To verify ownership of your domain, you need to add two DNS records: + +1. **CNAME Record**: Points your domain to Rownd's authentication servers + - Name: Your custom domain (e.g., auth.acme.com) + - Value: The provided Rownd endpoint (e.g., eijl7ms.auth.rownd.com) + +2. **TXT Record**: Verifies your ownership of the domain + - Name: _cf-custom-hostname.your-domain (e.g., _cf-custom-hostname.auth.com) + - Value: The provided verification string (e.g., 5edk2cd9-030da-453d-8450-8221b2aasdfasf) + +Add these records through your DNS provider's management console: + +![Example DNS configuration in Cloudflare](cloudflare-example.png) + +#### DNS Provider Instructions + +We provide step-by-step instructions for configuring DNS records with popular providers: + +- [Cloudflare](/configuration/custom-domains/dns-records#1-cloudflare) +- [GoDaddy](/configuration/custom-domains/dns-records#2-godaddy) +- [Google Cloud DNS](/configuration/custom-domains/dns-records#3-google-cloud-dns) +- [AWS Route 53](/configuration/custom-domains/dns-records#4-aws-route-53) +- [Azure DNS](/configuration/custom-domains/dns-records#5-azure-dns) +- [Namecheap](/configuration/custom-domains/dns-records#6-namecheap) +- [DigitalOcean DNS](/configuration/custom-domains/dns-records#7-digitalocean-dns) +- [Hover](/configuration/custom-domains/dns-records#8-hover) +- [DNS Made Easy](/configuration/custom-domains/dns-records#9-dns-made-easy) +- [Dyn Managed DNS](/configuration/custom-domains/dns-records#10-dyn-managed-dns) +- [Squarespace](/configuration/custom-domains/dns-records#11-squarespace) + +For detailed instructions on setting up DNS records with your specific provider, see our [DNS Provider Steps](/configuration/custom-domains/dns-records). + +### Step 4: Wait for Verification + +After adding the DNS records, Rownd will automatically verify your domain. This process typically takes 5-10 minutes but can sometimes take up to 24-48 hours, depending on your DNS provider's propagation time. + +Once verified, your domain will show as "Verified - Inactive": + +![Domain showing as verified but inactive](verified-inactive.png) + +### Step 5: Activate Your Custom Domain + +Click the "Activate" button to start using your custom domain for authentication. Once activated, all authentication flows, emails, and links will use your custom domain. + +![Active custom domain ready for use](active-custom-domain.png) + +## Link Domains + +In addition to your primary authentication domain, you can also configure link domains for Smart Links. These domains are used when creating deep links to your application for authentication flows, app installs, and user onboarding. + +To add a link domain, navigate to the "Link domains" section below your primary authentication domain settings. + +### Smart Links with Custom Domains + +[Smart Links](/magic-links/overview) can be used with your custom domains to create a seamless branded experience for your users. These links function similarly to Branch links, providing powerful attribution and deep linking capabilities, but with full customization under your own domain. + +Smart Links can be used in various scenarios: + +- **[Authenticated Experiences](/magic-links/authenticated)**: Send authenticated deep links that maintain user context and session state +- **[Unauthenticated Experiences](/magic-links/unauthenticated)**: Create public links for app installs, onboarding flows, or marketing campaigns +- **[Cross-Platform Experiences](/magic-links/platform)**: Direct users to the appropriate experience based on their device and context + +By using a custom domain for your Smart Links, you enhance brand trust and recognition while maintaining all the functionality of Rownd's link management system. + +## Troubleshooting + +If your domain verification fails to complete: + +1. **Check DNS Configuration**: Ensure both CNAME and TXT records are correctly configured +2. **Wait for Propagation**: DNS changes can take time to propagate globally +3. **Verify Domain Format**: Ensure your domain format matches exactly what's specified in the Rownd dashboard +4. **Contact Support**: If issues persist, contact Rownd support for assistance + +## Notes and Limitations + +- Each Rownd application can have one active authentication domain at a time +- You can have multiple verified domains but only one can be active +- Custom domains require proper SSL/TLS certificate configuration, which Rownd handles automatically +- Custom domain email deliverability may require additional SPF/DKIM configuration for optimal results diff --git a/rownd-docusaurus/docs/configuration/custom-domains/settings-custom-domains.png b/rownd-docusaurus/docs/configuration/custom-domains/settings-custom-domains.png new file mode 100644 index 0000000..8c45953 Binary files /dev/null and b/rownd-docusaurus/docs/configuration/custom-domains/settings-custom-domains.png differ diff --git a/rownd-docusaurus/docs/configuration/custom-domains/verification-custom-domains.png b/rownd-docusaurus/docs/configuration/custom-domains/verification-custom-domains.png new file mode 100644 index 0000000..5e87223 Binary files /dev/null and b/rownd-docusaurus/docs/configuration/custom-domains/verification-custom-domains.png differ diff --git a/rownd-docusaurus/docs/configuration/custom-domains/verified-inactive.png b/rownd-docusaurus/docs/configuration/custom-domains/verified-inactive.png new file mode 100644 index 0000000..65fe9a0 Binary files /dev/null and b/rownd-docusaurus/docs/configuration/custom-domains/verified-inactive.png differ diff --git a/rownd-docusaurus/docs/configuration/customizations/email-customization.mdx b/rownd-docusaurus/docs/configuration/customizations/email-customization.mdx new file mode 100644 index 0000000..2cf8431 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/customizations/email-customization.mdx @@ -0,0 +1,119 @@ +--- +title: "Pre-built UI" +description: + "Rownd provides a comprehensive set of pre-built UI components that are fully customizable to align with your company's branding and user experience requirements. These components are optimized for both web and mobile platforms, reducing development effort while maintaining flexibility." +--- + +## UI Components + +Each of the following sections outlines a specific UI element, its purpose, and customization options. + +You can modify these UI components in the Design tab within the Rownd platform: +- In the **Design tab** + - **Theme tab:** Apply global branding, including colors, typography, and logos. + - **Customize UI tab:** Adjust content, wording, and visibility settings. +- **Sign-in Methods tab:** Configure authentication method order and visibility. + +![Customize UI tab in Platform](/images/prebuilt-ui-customize-UI-tab.png) + +### Sign-in Modal +This modal appears when a user attempts to sign in. It provides authentication options based on the methods configured in your Rownd platform. + +**Customizable elements:** +- Order and visibility of sign-in methods (Sign-in Methods tab) +- Content and wording (Customize UI tab) +- Branding, including logos and colors (Theme tab) + +![Sign-in modal examples](/images/prebuilt-ui-sign-in-modal.png) + + +### Profile +The Rownd Profile enables users to manage their account information without requiring custom development. It consists of the following sections: + +- **Account Information**: Displays enabled sign-in methods, allowing users to update their email, phone number, or connect accounts like Google. +- **Personal Information**: Stores non-authentication data, such as names and addresses. Fields can be customized from the Profile Data tab. Users can edit data unless marked as app-owned. +- **Preferences**: Displays the account ID (for support), a "Sign out of all sessions" option (which signs users out of all devices), and an "Account deletion" feature. + +*Future updates will include session management, passkey management, and more.* + +**Customizable elements:** +- Fields in Account Information (Sign-in Methods tab) +- Fields in Personal Information (Profile Data tab) +- Branding and styling (Theme tab) + +![Profile examples](/images/prebuilt-ui-profile.png) + + +### Verification Modal +This modal appears when users need to verify their email or phone number during sign-in. + +**Customizable elements:** +- Title and failure messages (Customize UI tab) +- Branding and visual elements (Theme tab) + +![Verification modal examples](/images/prebuilt-ui-verification-modal.png) + + +### Verification Screen +After users verify their phone number or email, they briefly see this screen before being redirected to your app or website. + +**Customizable elements:** +- Currently, this screen inherits Theme settings. +- Future updates will allow content customization in the Customize UI tab. + +![Verification screen examples](/images/prebuilt-ui-verification-screen.png) + + +### Rownd Verification Email +Users receive this email to verify their email address during sign-in. + +**Customizable elements:** +- Language and wording (Customize UI tab) +- Company logo. colors,and corner radius (Theme tab) + +> **Note:** If you prefer to have Rownd verification emails sent from an email address on your own domain (e.g., hello@mycompany.com), we can configure that for you. Send an email to support@rownd.io with the subject line From email address change. We’ll process your request in about one business day and reply with further instructions to finalize the setup. + +![Rownd email examples](/images/prebuilt-ui-email.png) + + +### Mobile Redirect Screen +When a user without your mobile app clicks a sign-in link on a mobile device, this screen directs them to download the app. + +**Customizable elements:** +- App store logo and branding (Theme tab) +- Content and wording (Customize UI tab) + +![Mobile app redirect screen examples](/images/prebuilt-ui-mobile-redirect-screen.png) + + +### Rownd Hub Widget +The Rownd Hub is an optional widget that provides a quick-access entry point for authentication and profile management. + +**Customizable elements:** +- Visibility (Customize UI tab) +- Branding and design (Theme tab) + +*The Hub can be useful for testing on web apps and websites.* + +![Hub examples](/images/prebuilt-hub.png) + + +### Automations UI +Certain UI elements are triggered through Automations in Rownd. These include: + +- Passkey modals +- Prompts for additional user information + +**Customizable elements:** +- Wording adjustments +- Ordering of fields +- Branding (Theme tab) + +![Automation UI examples](/images/prebuilt-ui-automation-ui.png) + +-------- + +Rownd’s pre-built UI components provide a powerful, flexible solution for authentication and user account management, saving significant development time. With extensive customization options, businesses can maintain brand consistency while leveraging secure, optimized UI elements across web and mobile platforms. + + + diff --git a/rownd-docusaurus/docs/configuration/customizations/global-style.mdx b/rownd-docusaurus/docs/configuration/customizations/global-style.mdx new file mode 100644 index 0000000..48858a6 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/customizations/global-style.mdx @@ -0,0 +1,60 @@ +--- +title: "Global style" +description: "Customize Rownd UI elements to match your brand and style" +--- + +Rownd offers a range of style customizations to best match your brand look and feel. + +#### Elements you can customize + +- **Appearance.** Depending on your application, you can decide if you want your styles to **1. Automatically sync with user OS settings**, 2. Always appear in **light mode** or 3. Always appear in **dark mode**. The default setting is to automatically sync to user OS setting. + +- **Primary color.** Rownd's default primary color is
Purple `#5B13DF`. You can + change this color to match your brand color. Additionally, if you are using dark mode or syncing to user OS settings, you can add a primary color for dark mode. Use the **Dark mode** toggle in the preview on the right to see your dark mode color in the preview. + +- **Overlay blurring.** By default, overlays (behind modals) blur the background. You can leave this on or turn it off. + +- **Visual elements.** Most Rownd dialogs include "visual swoops" at the bottom that match the primary color you select. You can choose to remove these for your application. Rownd also includes default illustrations that appear on varying modals. You can choose to remove these as well. + +- **Corner radiuses.** By default, Rownd modal and hub corners have rounded edges; you can choose between rounded and square corners on UI elements. + +- **Logos.** Logos can be added to sign in modals by checking the box to "Include app logo in Rownd modals." You may add separate logos for light and dark mode or upload the same logo for both appearances. + +![Customize Rownd with your branding and style on the "Design" tab.](/images/Global-style-wondr.png) + +#### How to customize + +1. In the Rownd dashboard, navigate to the **Design** tab from the left navigation. + +2. Edit and change dark mode options, the primary color, corners, background blur, and visual + elements with the options on the left side of the screen. + +4. Preview your changes in an example UI dialog on the right side of the screen. + +5. Press **Save** in the top-right corner before leaving the page. Your updates will be applied to the websites and apps where you've installed the Rownd code snippet. + +
+ +#### Additional UI customizations + +Global styles will span across all Rownd UI elements, but you have additional customization options for the content and appearances of Rownd emails, modals, and screens. + +- **[Email customizations](/configuration/customizations/email-customization).** Customize the language and logo that appear in user verification emails for email sign in. + +- **Sign in modal.** From the "Modals" tab, you can update the content, visuals, and links on your Rownd sign in modal. + +- **Verification modal.** From the "Modals" tab, you can update the content and visuals on your Rownd verification modal. + +- **App download screen.** From the "Emails and screens" tab, you can update the content and visuals on the Rownd App download screen. This screen appears if your user is attempting mobile app sign in and does not yet have the app on their device. Be sure to configure your [mobile app settings](/configuration/mobile/overview) for this to work properly. + +
+ + + +If your app is already in production, you may want to create a second Rownd app in order to test your changes before applying them to your live environment. + + + +You can use the **Reset to default settings** option on the right side of the page +to reset the style to the Rownd defaults. + diff --git a/rownd-docusaurus/docs/configuration/customizations/sub-brands.mdx b/rownd-docusaurus/docs/configuration/customizations/sub-brands.mdx new file mode 100644 index 0000000..93dd95a --- /dev/null +++ b/rownd-docusaurus/docs/configuration/customizations/sub-brands.mdx @@ -0,0 +1,59 @@ +--- +title: "Sub-brands" +description: "Sub-brands allow you to manage users across all your varying apps, websites and products" +--- + +Introducing sub-brands, one of Rownd’s latest and greatest features focused on allowing you to expand your portfolio without partitioning where you manage your users. Sub-brands are extremely unique, easy to use, and can save you and your development team so much time. + + +#### What are sub-brands? + +A sub-brand is a variation of your Rownd application. Sub-brands can have their own theme, customizations, and even associated automations. All sub-brands share users with the base app, which means that users maintain their account and profile information across the sub-brands they are signed into. Sub-brands allow you to see which apps and brands your users have interacted with, without having to use multiple Rownd apps. + +When you add a user to a sub-brand or they sign into one of your apps that uses a specific sub-brand, an attribute called `rownd:app_variants` is added to their profile with a list of any sub-brands with which the user has interacted. You can also manage these attributes to add or remove a user from a sub-brand. + +Additionally, when the user signs in or out of a sub-branded app, their profile metadata will include a map of each sub-brand containing the sign-in method used and the last time they signed in. + + +#### Why might you enable sub-brands? + +Sub-brands are most often used when customers have multiple brands or style considerations for different environments like their web app, mobile app, or blog site. Here are a few examples and use cases: + +- League or collection of apps: For example, a sports league wants sign-ins for their rewards program, but each team has its own application and requirements. In this scenario, the base Rownd app would represent the league, and each team would be its own sub-brand. This way, each team could still have its logo and branding colors, as well as its sign-in method configuration, while at the base app level, the league can see which users have interacted with each team (sub-brand), and users can easily sign in across team apps. + +- Parent brand scenario: When one company owns multiple brands (Example: Walt Disney Company owning ESPN, Hulu, Disney +, ABC, etc.), they’d want to know which customers are interacting with which apps, without those users having a separate account for each app. By using sub-brands, the parent brand can better understand their users in seeing where they are visiting. + +- Testing scenario: You can also use sub-brands as a way of testing your Rownd flow without impacting production users. Since you can attach a specific app key to a sub-brand, you can create a sub-brand with changes that you'd like to change and use its app key in a separate testing environment to validate the changes. + + + +#### How to enable and use sub-brands: + +1. From the Rownd platform, navigate to the design tab. + +2. In the design tab, you’ll see a sub-brands tab (with “Beta” tag). + +![Customize Rownd with your branding and style on the "Design" tab.](/images/welcome-to-sub-brands.png) + +3. From that tab, you can add your first sub-brand. Give it a name and an optional description, and press create! + +![Customize the details of your first sub-brand.](/images/create-new-sub-brand.png) + +4. From here, you can use the drop-down and change the design theme. + +5. To install in your app, grab the app key either from the app key tab or from the sub-brands tab. Include it in the Rownd SDK configuration or add it to the Javascript snippet. + +![Install sub-brands in your apps with their brand specific keys.](/images/sub-brand-app-key.png) + +6. Once users start signing into your apps, you’ll be able to see the sub-brands they have interacted with from the users table. The really cool thing here too is that their profile and account information will persist across sub-brands and the base app! + + +
+ +#### Base brands vs. Sub-brands + +Your base brand is the original branding and style you configured for your Rownd app. When you add a sub-brand, the sub-brand will initially take on the same styling as your base brand (colors, logos, styles, etc.) until you change them. If you don't customize a style aspect of a sub-brand, and later change that aspect in the base brand, the sub-brand will adopt the base brand's change. For example, if you haven't updated the corner radius of a sub-brand from the base brand's 3px radius, and then change the base brand's corner radius to 10px, all sub-brands that weren't already customizing the corner radius will now adopt a 10px corner radius. + + +We love feedback! If you try out this feature, please reach out and let us know what you think and any feedback or questions you have at Support@rownd.io. + diff --git a/rownd-docusaurus/docs/configuration/integrations/airtable.mdx b/rownd-docusaurus/docs/configuration/integrations/airtable.mdx new file mode 100644 index 0000000..d8549c3 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/airtable.mdx @@ -0,0 +1,74 @@ +--- +title: "Airtable" +--- + +The Rownd integration for Airtable lets you sync personal information between +Rownd and a single Airtable Table. When configured, PII stored in the Table will +be discoverable and manageable by the data owners. + +#### Creating the integration + +1. From the **Integrations** tab in the sidebar, click on the **Add + Integration** button. If this is your first time creating an integration, + you'll already be in the Connector Catalog and don't need to click the + button. + +2. Choose the **Airtable** connector from the Connector Catalog + +3. Enter a name for your new Integration. + +After you've entered a descriptive name, click **Next** + +1. Authenticate with Airtable + +Enter an API key that Rownd can use for reading and writing to Airtable. You can +create or retrieve your API key from the Airtable +[account settings](https://airtable.com/account) under the **API** heading. + +Click the **Next** button after entering your API key. + +1. Airtable Settings + +Select the Airtable Base and Table + +When done, click **Next** + +1. Last Modified Time Field + +In this step, Rownd will check for the existence of a `lastModifiedTime` Field +within your chosen Table. This is a special field type that Airtable uses to +record the last time an entry in the Table was updated. if necessary, please add +this Field (with any name) to your Table and click the **Retry** button. +Otherwise, click **Create** to finish. + +For more inormation on adding a `lastModifiedTime` Field, please check out the +[Airtable Documentation](https://support.airtable.com/hc/en-us/articles/360022745493-Last-modified-time-field) + +Click the **Create** button to finish creating your Integration + +**Attach your Integration to a Rownd Application** + +After creating your Integration, you must attach it to an existing Rownd +application. + +1. From the Integrations table, click the overflow icon on your new Integration + and select **Attach to application** + +2. Choose the application from the selector and click **Next** + +3. Map data between the Rownd application and your new Integration + +You will see a list of all fields that exist in your chosen application's +schema. Choose the corresponding Field within your Airtable Table. + +For instance, you could have a field in your Rownd application called +`first_name` and a corresponding Field in your Table called `firstName`. Choose +the `firstName` options in the dropdown next to `first_name`. + +A mapping for the `email` field is required. Rownd uses this field to identify +and search for users. + +Rownd can only manage fields for which you have provided a mapping. Therefore, +define as many mappings as possible to get the most value from Rownd. + +Once you complete the mapping, click **Save**. diff --git a/rownd-docusaurus/docs/configuration/integrations/auth0.mdx b/rownd-docusaurus/docs/configuration/integrations/auth0.mdx new file mode 100644 index 0000000..0f5d021 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/auth0.mdx @@ -0,0 +1,19 @@ +--- +title: Auth0 +--- +The Auth0 integration helps you migrate your user authentication from Auth0 to Rownd. The migration can be done in one sync operation or on-demand as users sign-in. Existing Auth0 users will maintain their user IDs in Rownd. + +#### Creating the integration + +1. From the **Integrations** tab in the sidebar, click on the **Add Integration** button. +2. Choose the **Auth0** connector from the Connector Catalog +3. Enter a name for your new integration. After you've entered a descriptive name, click **Next** +4. Enter your client credentials and environment domain + + + The client credentials that you provide must be for a "Machine-to-Machine" application. Rownd uses these credentials to make calls to the Auth0 Management API to lookup user info. Find out more about creating the client credentials [here.](https://auth0.com/docs/get-started/auth0-overview/create-applications/machine-to-machine-apps) + + +When the connection is ready, you can use the three-dots menu on the far right of the row to attach the connection to your app. + +Once these steps are completed, you should be able to use Rownd to sign in as an existing Auth0 user, receiving the same ID that you had previously. diff --git a/rownd-docusaurus/docs/configuration/integrations/firebase/authentication.mdx b/rownd-docusaurus/docs/configuration/integrations/firebase/authentication.mdx new file mode 100644 index 0000000..cc45fa2 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/firebase/authentication.mdx @@ -0,0 +1,40 @@ +--- +title: Firebase Authentication +--- +The Firebase Authentication integration helps you migrate your user authentication flow from Firebase to Rownd. It also provides the means to use Rownd and Firebase Firestore together. + +Before you begin, check out the Google Cloud [prerequisites](/configuration/integrations/firebase/google-cloud-platform-requirements) +to ensure your GCP account and Project are ready to integrate with Rownd. + +#### Creating the integration + +1. From the **Integrations** tab in the sidebar, click on the **Add + Integration** button. + +2. Choose the **Firebase - Authentication** connector from the Connector + Catalog + +3. Enter a name for your new integration. + After you've entered a descriptive name, click **Next** + +4. Click the **Begin authentication** button to sign in to your Google Account and grant Rownd access to your Firebase project. + + + Firebase Authentication runs on Google Cloud. Rownd leverages the Google + Cloud Platform to receive updates from Firebase as any users are created, modified, or deleted. Rownd will need permission to read Google Cloud Projects, read and write Firebase resources, and create + Cloud Functions. For a full list of access that Rownd + needs, click + [here](/rownd/guides/configuration/integrations/firebase/google-cloud-platform-requirements#access-requirements). + + + Grant Rownd the access to your Google Account, and then click the **Next** + button when authentication is complete. + +5. Select the Firebase Project and Application that you'd like to link with Rownd. + When finished, click **Create** + + Initialization of the integration may take a few minutes while Rownd creates the required links with your Firebase project. You can track its progress in the **Connections** tab of the Integrations area. + +When the connection is ready, you can use the three-dots menu on the far right of the row to attach the connection to your app. + +Once these steps are completed, you should be able to use Rownd to sign in as an existing Firebase user, receiving the same ID that you had previously. diff --git a/rownd-docusaurus/docs/configuration/integrations/firebase/google-cloud-platform-requirements.mdx b/rownd-docusaurus/docs/configuration/integrations/firebase/google-cloud-platform-requirements.mdx new file mode 100644 index 0000000..7240b29 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/firebase/google-cloud-platform-requirements.mdx @@ -0,0 +1,34 @@ +--- +title: "Google Cloud Platform requirements" +--- + +#### Prerequisites + +Rownd leverages the power of the Google Cloud Platform to configure the link between Firebase and Rownd. As +such, there are prerequisites that Rownd requires prior to setting up a new integration. + +**Billing Account** + +The GCP Project where your Realtime Database instance resides must have an +associated billing account enabled. Go +[here](https://cloud.google.com/billing/docs/how-to/manage-billing-account) for +help establishing a billing account. + +**Permissions** + +Rownd will request access to your GCP account via OAuth 2.0 scopes during the +authentication step. Your user must have and provide sufficient permissions to satisfy +Rownd's request. See the [Access Requirements](#access-requirements) section +below for a full list of permissions that Rownd needs. + +#### Access Requirements + +Rownd will need the following Google Cloud Platform permissions to create and +run the Cloud Functions that alert Rownd of changes in your Firebase projects + +| Firebase Product/Integration | Permission Scope | Reason | +| --------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------- | +| All | https://www.googleapis.com/auth/cloud-platform | Creating a Rownd Service Account, Listing Projects, and Listing Project resources | +| All | https://www.googleapis.com/auth/iam | Assigning IAM access policies and membership for the Rownd Service Account | +| All | https://www.googleapis.com/auth/service.management | Enabling API Services in the Project | +| Realtime Database | https://www.googleapis.com/auth/firebase.database | Access to the Firebase Realtime Database API | diff --git a/rownd-docusaurus/docs/configuration/integrations/firebase/overview.mdx b/rownd-docusaurus/docs/configuration/integrations/firebase/overview.mdx new file mode 100644 index 0000000..004d434 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/firebase/overview.mdx @@ -0,0 +1,8 @@ +Rownd integrates with various Firebase product offerings in order to help the two systems work well together for any use case. + +Rownd currently integrates with two Firebase products: + +1. [Firebase Authentication](/configuration/integrations/firebase/authentication) +2. [Firebase Realtime Database](/configuration/integrations/firebase/realtime-database) + +Feel free to explore these integrations further to enhance your project's functionality and streamline its performance. Should you require any assistance or have inquiries, our support team stands ready to assist you. diff --git a/rownd-docusaurus/docs/configuration/integrations/firebase/realtime-database--defining-user-data-locations.mdx b/rownd-docusaurus/docs/configuration/integrations/firebase/realtime-database--defining-user-data-locations.mdx new file mode 100644 index 0000000..337a188 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/firebase/realtime-database--defining-user-data-locations.mdx @@ -0,0 +1,188 @@ +--- +title: "Examples: Defining user data locations" +sidebarTitle: "Realtime Database: Examples" +--- + +User data can exist in various locations throughout a database. The following +are some examples of various scenarios and how to define the user data locations +appropriately. + +### User Data Stored in a Single Location + +If your user data is stored under a single database path, defining the user data +locations is quite simple. + +#### Example Database + +```json +{ + "users": { + "user1": { + "email": "john@gmail.com", + "first_name": "John", + "last_name": "Doe" + }, + "user2": { + "email": "jane@gmail.com", + "first_name": "Jane", + "last_name": "Doe" + } + }, + + "otherData": {} +} +``` + +#### User Data Location + +- Path: `/users` + +- Foreign Key: _not required_ + +- Reference: _not required_ + +The `Foreign Key` and `Reference` are not required since the user data is stored +in one location. There are no other locations in the database that reference +this path or contain additional personal data. + +### User data stored in multiple locations + +When user data is stored in multiple locations in the database, you will use a +combination of all three location fields `Path`, `Foreign Key`, and `Reference`. +The following example will help you see how and when to use the two different +types of `Foreign Key` values. + +#### Example Database + +```json +{ + "users": { + "user123": { + "first_name": "John", + "last_name": "Doe" + } + }, + "addresses": { + "user123": { + "street": "1974 Wolfpack Ln", + "city": "Raleigh", + "state": "NC", + "zip": "27608" + } + }, + "emailVerification": { + "ev123": { + "email": "john@gmail.com", + "userId": "user123", + "verified": true + } + } +} +``` + +#### User Data Locations + +For this example, we'll need to define several user data locations. + +- Path: `/users` + +- Foreign Key: _not required_ + +- Reference: _not required_ + +This location captures the database users the same way that we did it in the +first example. + +- Path: `/addresses/{userId}` + +- Foreign Key: `{userId}` + +- Reference: `/users/{userId}` + +This location will capture the database addresses and connect that data back to +the user objects. Notice that curly braces `{}` surround the `Foreign Key`. By +convention, the curly braces tell Rownd that the value of the foreign key comes +a path variable named `userId`. + +Rownd will search the database for user data on the `/addresses` path. In this +example, it will find data at `/addresses/user123`. This will be the resolved +path, and the resolved foreign key value will be `user123`. Rownd will replace +`{userId}` in the `Reference` with `user123` and grab additional user data from +`/users/user123`. + +The `Reference` value must always include the `Foreign Key`. + +- Path: `/emailVerification` + +- Foreign Key: `userId` + +- Reference: `/users/{userId}` + +This location will capture the user data stored under the `/emailVerification` +path. The lack of surrounding curly braces in the `Foreign Key` tells Rownd to +look for a corresponding _field_ within the database object at the resolved +path. + +Rownd will search the database for user data on the `/emailVerification` path. +In this example, it will find data at `/emailVerification/ev123`. At that path, +Rownd will look for a field in the object named `userId`. It will find this +document: + +```json +{ + "email": "john@gmail.com", + "userId": "user123", + "verified": true +} +``` + +In this case, the resolved foreign key value will be `user123`. Rownd will +replace the `userId` field in the `Reference` with `user123` and look for +additional user data on the `/users/user123` path. + +### Using a wildcard path + +There are cases where you may not know the exact path to user data because it is +stored under an arbitrary or unique field like an ID. In such a case, you can +use the `*` wildcard character in the `Path`. You can only use the wildcard +character once in a path, but it can be a powerful tool. Here is an example. + +#### Example Database + +```json +{ + "users": { + "user123": { + "profile": { + "first_name": "John", + "last_name": "Doe" + } + }, + "user456": { + "profile": { + "first_name": "Jane", + "last_name": "Doe" + } + } + } +} +``` + +Notice that the actual user data is stored within the `profile` key of the users +objects. To explicitly define paths for this user data, you would have to define +two user data locations: + +- `/users/user123/profile` + +- `/users/user456/profile` + +That is unreasonable in a real-world scenario where you have thousands of users. +To handle these use cases, you can define a path with the wildcard character +like `/users/*/profile` to match all users and locate the data as existing in +the `profile` child field. + +You can use the wildcard character `*` and a foreign key in the path. For +example, you could define a `Path` as `/orgs/*/users/{userId}` where `{userId}` +is the `Foreign Key.` + +You can also use wildcards in `Reference` values. diff --git a/rownd-docusaurus/docs/configuration/integrations/firebase/realtime-database.mdx b/rownd-docusaurus/docs/configuration/integrations/firebase/realtime-database.mdx new file mode 100644 index 0000000..26587ea --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/firebase/realtime-database.mdx @@ -0,0 +1,175 @@ +--- +title: "Firebase - Realtime Database" +sidebarTitle: "Realtime Database" +--- + +The Firebase Realtime Database integration lets you sync personal information +between Rownd and a single Firebase Realtime Database (RTDB) instance. When +configured, PII stored inside of an RTDB instance will be discoverable and +manageable by the data owners. All of this is done by leveraging Google Cloud +Functions and the Rownd platform. + +Check out the Google Cloud +[prerequisites](/configuration/integrations/firebase/google-cloud-platform-requirements) +to ensure your GCP account and Project are ready for the Rownd Integration. + +#### Creating the integration + +1. From the **Integrations** tab in the sidebar, click on the **Add + Integration** button. + +2. Choose the **Firebase - Realtime Database** connector from the Connector + Catalog + +3. Enter a name for your new integration. + After you've entered a descriptive name, click **Next** + +4. Click the **Begin authentication** button and sign in to your Google Account to grant Rownd access to your Firebase project. + + + Firebase Realtime Database runs on Google Cloud. Rownd leverages the Google + Cloud Platform to receive Realtime Database updates. Rownd will need permission + to read Google Cloud Projects, read and write Firebase resources, and create + Cloud Functions. For a full list of access that Rownd + needs, click + [here](/rownd/guides/configuration/integrations/firebase/google-cloud-platform-requirements#access-requirements). + + + Grant Rownd the access to your Google Account, and then click the **Next** + button when authentication is complete. + +5. Select the Firebase Project, Application, and Database that you'd like to link with Rownd. + + When finished, click **Next** + +6. In the **Database Settings** step, you will provide Rownd with information about +where and how personal information is stored within your Firebase Realtime +Database. + + The RTDB structure is essentially a large JSON object. You will specify the JSON + path to where the personal information exists. If PII is stored in multiple + places within the database, you can add multiple paths to the configuration. + +#### Defining User Data Locations + +Each entry in the User Data Locations list has three fields; `Path`, +`Foreign Key`, and `Reference`. + +- `Path` (required) - The database location where PII is stored. The value is a + JSON path like `/path/to/data` + +For each unique `Path` that you provide, Rownd will create a Google Cloud +Function configured to send updates to Rownd whenever data under that path +changes. As you construct this list of paths, consider all database locations +where PII is stored. + + +The `Path` can include the wildcard character `'*'` if the PII is stored nested +beneath an arbitrary or unique field (like an ID). + +For instance, PII could be stored at `/users/user123/profile` or +`/users/user456/profile`. In such a case, you could define the path with the +wildcard character to match both paths: `/users/*/profile`. + + + + + The wildcard character `'*'` can only be used once within a path. + + +- `Foreign Key` \- The field name within the database document, or path + variable, whose value references another location in the database + +This value can have two forms: + +**Object Field** + +The `Foreign Key` can reference a field within the database object. For +instance, if the document at `/addresses` looks like: + +```json +{ + "userId": "user123", + "street": "1983 Wolfpack Ln", + "city": "Raleigh", + "state": "NC", + "zip": "27609" +} +``` + +A valid `Foreign Key` would be `"userId"`. The resolved value would be +`"user123"`. + +**Path Variable** + +The `Foreign Key` can reference a path variable. For instance, if the `Path` is +`/addresses/{userId}`, the `Foreign Key` can be `{userId}`. Rownd will interpret +the value of the foreign key as its matched value in a resolved path. (e.g. a +resolved path of `/addresses/user123` would yield a foreign key value of +`"user123"`) + +By convention, `Foreign Keys` defined with surrounding curly braces `{}` will be +interpreted as path variables. `Foreign Keys` without curly braces will be +assumed document field names. + +- `Reference` \- A database location where the Foreign Key's resolved value can + be used to retrieve additional PII. `Reference` is only used in combination + with a `Foreign Key`. + +This value will always be a JSON path and include the `Foreign Key` within it +surrounded by curly braces `{}`. For instance, if `Foreign Key` is `"userId"`, +then the path could look something like `"/users/{userId}/profile"` + +For more examples of defining user data locations, see the +[examples section](/rownd/guides/configuration/integrations/firebase/realtime-database--defining-user-data-locations). + +1. Create the Integration + +Once you're satisfied with the database configuration, click on **Create** to +create your Integration. + +Creation will take a couple of minutes. Rownd is busy creating and configuring +resources within your GCP Project. While you wait, feel free to track the +progress in the Integrations table by hovering over the Integration's status. + +**After Creation** + +**Database Indexes** + +Depending on the configured paths in step #5 (**Database Settings**), Rownd may +require certain indexes within your Realtime Database Rules. Rownd will show you +the expected database indexes in the confirmation screen after you create your +new Integration. + +Transfer those indexes into your database rules via the Firebase UI + +Find out more about how to create Realtime Database rules +[here](https://firebase.google.com/docs/database/security/indexing-data). + +**Attach your Integration to a Rownd Application** + +After creating your Integration, you must attach it to an existing Rownd +application. + +1. From the Integrations table, click the overflow icon on your new Integration + and select **Attach to application** + +2. Choose the application from the selector and click **Next** + +3. Map data between the Rownd application and your new Integration + +You will see a list of all fields that exist in your chosen application's +schema. Enter the name of the corresponding field within your Firebase Realtime +Database. + +For instance, you could have a field in your Rownd application field called +`first_name` and a corresponding field in your Realtime Database called +`firstName`. Enter `firstName` into the input box next to `first_name`. + +A mapping for the `email` field is required. Rownd uses this field to identify +and search for users. + +Rownd can only manage fields for which you have provided a mapping. Therefore, +define as many mappings as possible to get the greatest value from Rownd. + +Once you finish mapping fields, click **Save** diff --git a/rownd-docusaurus/docs/configuration/integrations/hubspot.mdx b/rownd-docusaurus/docs/configuration/integrations/hubspot.mdx new file mode 100644 index 0000000..c0a0c25 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/hubspot.mdx @@ -0,0 +1,60 @@ +--- +title: "Hubspot" +--- + +The Rownd integration for Hubspot makes it easy to keep your contact list in sync. The integration will automatically create a new contact or update an existing one in your Hubspot account. + +#### Setup + +The Hubspot integration can be enabled from the [Rownd dashboard.](https://app.rownd.io) + +1. From the menu, select **Integrations.** + +2. Select the **Connector catalog** tab. + +3. From the list of available connectors, click on the **Hubspot** + entry. The connector setup dialog will appear. + +4. Enter a descriptive name and click **Next**. + + ![Create the Hubspot integration](/images/integration_hubspot_setup.png) + +#### Authenticate + +1. Click **Begin authenticate** and log in to your Hubspot account + +2. Grant Rownd access to your Hubspot account, and then click **Next** + +![Create the Hubspot authentication](/images/integration_hubspot_authenticate.png) + +### Optional setting + +To manage email subscriptions, specify the subscription id and the data field to map. + +![Create the Hubspot settings](/images/integration_hubspot_settings.png) + +4. Click **Create** to create the connection. + +The dialog should indicate that the integration was created successfully. Now that the connection exists, we need to attach it to an application. + +#### Attach to an application + +1. From the Integrations table, click the overflow icon on your new Integration + and select **Attach to application** + +2. Choose the application from the selector and click **Next** + +3. Map data between the Rownd application and your new Integration + + +A mapping for the `email` field is required. Rownd uses this field to identify +and search for existing subscribers in your Hubspot account. Rownd can only manage fields for which you have provided a mapping. + + +4. Click **Save.** + +After a moment, the attached application should appear in the row next to the +connection. Once this occurs, data updates should begin flowing through the +integration. + + diff --git a/rownd-docusaurus/docs/configuration/integrations/mailerlite.mdx b/rownd-docusaurus/docs/configuration/integrations/mailerlite.mdx new file mode 100644 index 0000000..9eeb76a --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/mailerlite.mdx @@ -0,0 +1,67 @@ +--- +title: "MailerLite" +--- + +The Rownd integration for MailerLite makes it easy to keep your subscriber list in sync. The integration will automatically create a new subscriber or update an existing one in your MailerLite account. + +#### Setup + +The MailerLite integration can be enabled from the [Rownd dashboard.](https://app.rownd.io) + +1. From the menu, select **Integrations.** + +2. Select the **Connector catalog** tab. + +3. From the list of available connectors, click on the **MailerLite** + entry. The connector setup dialog will appear. + +4. Enter a descriptive name and click **Next**. + + ![Create the mailerlite integration](/images/integration_mailerlite_setup.png) + +#### Authenticate + +Enter your MailerLite API key. You can create or retrieve your API key from your MailerLite account. + +1. In your MailerLite account, navigate to the [Integrations](https://dashboard.mailerlite.com/integrations) page. + +2. Under MailerLite API click **Use**. + +3. Click **Generate new token**. + +4. Name your new token and copy/paste it into the field in the Rownd dialog. + +![Enter your MailerLite API key](/images/integration_mailerlite_auth.png) + +5. Click **Create** to create the connection. + +The dialog should indicate that the integration was created successfully. Now that the connection exists, we need to attach it to an application. + +![MailerLite connection success](/images/integration_mailerlite_success.png) + +#### Attach to an application + +1. From the Integrations table, click the overflow icon on your new Integration + and select **Attach to application** + +2. Choose the application from the selector and click **Next** + +![Attaching your connection to an application](/images/integration_mailerlite_attach.png) + +3. Map data between the Rownd application and your new Integration + +![Mapping your data fields](/images/integration_mailerlite_fields.png) + + +A mapping for the `email` field is required. Rownd uses this field to identify +and search for existing subscribers in your MailerLite account. Rownd can only manage fields for which you have provided a mapping. + + +4. Click **Save.** + +After a moment, the attached application should appear in the row next to the +connection. Once this occurs, data updates should begin flowing through the +integration. + +![Mailerlite connection attached to an application](/images/integration_mailerlite_done.png) + diff --git a/rownd-docusaurus/docs/configuration/integrations/overview.mdx b/rownd-docusaurus/docs/configuration/integrations/overview.mdx new file mode 100644 index 0000000..6d1c228 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/overview.mdx @@ -0,0 +1,33 @@ +--- +title: "Overview" +description: "Rownd offers a growing list of integrations with other cloud services, CRMs, and more. Here's a list of the integrations we currently support." +--- + +We can seamlessly synchronize data between Rownd and connected +services, keeping all of your user account information in sync across +all of the tools you use. For example, when you add a potential lead to HubSpot, +Rownd will automatically be aware of that contact and can attach their metadata +to their account when they sign in with their email address or phone number. If +the user corrects information in their profile (e.g., fixing a typo in their +last name), Rownd will propagate that change back to HubSpot. + +Not all of our integrations are currently user-configurable, so +[get in touch](https://rownd.io/contact) with us if you want to use one of the +ones that aren't yet self-service. We're happy to help! + + +Integrations are a beta feature, so you may not see them in your account yet. As a result, there may be bugs and documentation may lag the available connectors. Contact us if you need them to be enabled in your account. + + +| Integration | Self-service? | +| --------------------------------------------------------------------------------------------------- | ------------- | +| [Airtable](./airtable) | Yes | +| [Auth0](./auth0) | Yes | +| [Firebase (Authentication)](./firebase/authentication) | Yes | +| [HubSpot](./hubspot) | Yes | +| Mailchimp | Yes | +| [MailerLite](./mailerlite) | Yes | +| [Token validator](./token-validator) | Yes | +| [Webhooks](./webhooks) | Yes | +| WooCommerce | Yes | +| Zapier | Yes | diff --git a/rownd-docusaurus/docs/configuration/integrations/token-validator.mdx b/rownd-docusaurus/docs/configuration/integrations/token-validator.mdx new file mode 100644 index 0000000..a79f0b9 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/token-validator.mdx @@ -0,0 +1,77 @@ +--- +title: "Token validator" +description: Validating third-party tokens +sidebarTitle: Token validator +--- + +Rownd's token validator allows you to authenticate a token issued by another authentication provider and exchange it for a Rownd token. This feature is useful when migrating to Rownd from another authentication provider and you want to prevent existing users from being signed-out during the transition. It can also be used when moving between contexts, such as when your code is embedded in an implementation that you don't directly control (e.g., a webview inside someone else's mobile app). + + +## Why it's important + +### Keeping users signed-in + +When transitioning to Rownd's adaptive authenitcation, it's often important to keep your existing users signed-in once you deploy Rownd. The token validator enables Rownd to accept and validate your users' existing tokens. That way, users won't be forced to sign in again due to the authentication provider upgrade. + +### Moving between apps or contexts + +If your app is embedded in one of your customers' apps, the "parent" app may have previously created its own user session. If the customer can pass you a token or similar data that can be validated either via a JWKset or a REST API, Rownd's token validator will validate the existing token and extract a user ID from the response so that a user can continue using your app without any friction. + + +## How to set it up + +To set up the token validator, you'll need to configure your authentication provider to issue a token that Rownd can validate. + +**Note:** If you do not see **Integrations** in the Rownd left-hand sidebar, please contact the Rownd support team at support@rownd.io for assistance. + +### Configuring the token validator + +To set up the token validator with a generic authentication provider, follow these steps: + +1. Navigate to **Integrations** in the Rownd platform sidebar. +2. Enter the API endpoint to be used for token validation. +3. Provide information enabling Rownd to extract a user ID +![Token Validator Setup screenshot](/images/token-validation-setup.png) +3. Attach it to an application + +#### Coming soon: + +In the near future, we'll also support the following configurations: +1. Adding an OpenID Configuration endpoint or a direct URL to a JWK endpoint that Rownd can use to verify an asymmetrically-signed JWT. +2. Adding an HMAC secret that can be used to verify a symmetrically-signed JWT. + +If none of the above configurations match your specific use case, please let us know. + +#### Reponding to requests from the token validator +When implementing an API for the token validator to call, the response should be a flat JSON object with properties +that match the configuration you supplied to the token validator setup above. For example, if you configured the token validator to extract a `userId` and `email` from the response, the response should look like this: + +```json +{ + "userId": "1234567890", + "email": "juliet@rose.com" +} +``` + +You can also include additional properties in the response, which will be stored in the user's profile in Rownd if they match the profile schema configured within Rownd. + +Providing a user ID in your API response is optional. If none is provided, Rownd will generate a new user ID. If the user ID is present, Rownd will use it instead, which may be helpful if you're trying to map users to an existing system. + +#### Handling cases where the token is invalid or the user isn't found +If the token Rownd passes to your API does not match an existing user, you should return either a 400 or a 404 status code, which will cause Rownd to abort the token exchange. + +### Firebase setup + +If you're using Firebase as your authentication provider, Rownd provides a separate integration. Follow these steps: + +1. Navigate to **Integrations** +2. Click on the **Firebase - Authenticaiton** card from the **Connector catalog** tab. +3. Authenticate with Firebase, providing Rownd scoped access for validation. +4. Select the desired **Project** and **App** (if applicable). +5. Save the integration, then attach it to your Rownd application to enable it. + +When existing users sign in via Rownd, we'll automatically preserve their Firebase ID and basic user information, which is especially useful if you're referencing users in a separate datastore via this ID. + +Once Rownd is fully implemented, your users will not have to "re-sign in" and Rownd will automatically create users inside of Rownd for them. + +For additional assistance setting up the token validator, please reach out to support@rownd.io. diff --git a/rownd-docusaurus/docs/configuration/integrations/webhooks.mdx b/rownd-docusaurus/docs/configuration/integrations/webhooks.mdx new file mode 100644 index 0000000..e46de1c --- /dev/null +++ b/rownd-docusaurus/docs/configuration/integrations/webhooks.mdx @@ -0,0 +1,161 @@ +--- +title: "Webhooks" +description: "Run your own logic when data changes within Rownd" +--- + +Often, multiple sources can create or update profile and account information for +your users. For example, sometimes your app might update profile fields for a +user, but other times the user might update other information from their +browser. In either case, some component of your system might need to know about +those changes as they occur. + +Rownd provides a webhook integration that can communicate with essentially any +HTTP-based system, letting you know when new data is created or when existing +data has changed. + +### Setup + +To enable one or more webhooks, you'll need to configure them through the +[Rownd dashboard.](https://app.rownd.io) + +1. From the menu, select **Integrations.** + +2. Select the **Connector catalog** tab. + +3. From the list of available connectors, click on the **Generic webhook** + entry. The connector setup dialog will appear. + +4. Enter a descriptive name for your webhook and click **Next**. + +5. Select your desired **HTTP method** and enter the URL of your webhook. (If + you're just testing, you might want to use something like + [webhook.site](https://webhook.site)) + +6. Click **Create** to create the connection. + +The dialog should indicate that the webhook was created successfully. Now that +the connection exists, we need to attach it to an application, which will +dispatch updates to the webhook as data changes occur. + +1. Select the **Configured connections** tab at the top of the page. + +2. Locate the webhook connection you just created and click the three-dots menu + on the right-hand side of the row. + +3. From the menu, select **Attach to application**. The **Attach connection** + dialog will appear. + +4. From the **Select an application** menu, select the application to which the + connection should be attached. Click **Next**. + +5. By default, the webhook will contain the field names as they appear within + Rownd. If you want to change any field names, you may do so by typing the + desired field name(s) into the **Map fields** page. + +6. Click **Save.** + +After a moment, the attached application should appear in the row next to the +connection. Once this occurs, data updates should begin flowing through the +webhook. + +### Payload reference + +Overall, the payload for the webhooks will be similar for creates, updates, and +deletes; however the payload will always include a lookup value (such as email +address or phone number) and meta indicating what triggered the webhook. + +Below are example payloads of each type of trigger. The main payload fields will +differ based on the fields you defined within Rownd. + +Remember, the HTTP method will match the value configured during connector +setup, regardless of the represented action. + +#### Data created + +```json +{ + "data": { + "email": "jrose@acme.com", + "first_name": "Juliet", + "last_name": "Rose", + "user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1" + }, + "redacted": [], + "meta": { + "operation": "data_insert", + "lookup_values": [ + { + "field": "email", + "value": "jrose@acme.com" + } + ] + } +} +``` + +#### Data updated + +```json +{ + "data": { + "email": "jrose@acme.com", + "first_name": "Juliet", + "last_name": "Rose", + "country": "United States", + "user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1" + }, + "redacted": [], + "meta": { + "operation": "data_update", + "lookup_values": [ + { + "field": "email", + "value": "jrose@acme.com" + } + ] + } +} +``` + +#### Data visibly changed + +```json +{ + "data": { + "email": "jrose@acme.com", + "first_name": "Juliet", + "last_name": "Rose", + "country": "<>", + "user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1" + }, + "redacted": ["country"], + "meta": { + "operation": "visibility_update", + "lookup_values": [ + { + "field": "email", + "value": "jrose@acme.com" + } + ] + } +} +``` + +#### Data deleted + +```json +{ + "data": { + "user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1" + }, + "meta": { + "operation": "delete", + "lookup_values": [ + { + "field": "email", + "value": "jrose@acme.com" + } + ] + } +} +``` diff --git a/rownd-docusaurus/docs/configuration/mobile/android-instant.mdx b/rownd-docusaurus/docs/configuration/mobile/android-instant.mdx new file mode 100644 index 0000000..1651b47 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/mobile/android-instant.mdx @@ -0,0 +1,158 @@ +--- +title: "Using Android Instant Apps" +sidebarTitle: "Instant apps" +description: "100% conversion from web to native mobile app" +--- + +Android Instant Apps allow users to experience your app without installing it from the Play Store — reducing friction and improving conversion. You can use this to deliver a fast, native authentication experience that gets users signed in before ever asking them to install your app. + +> ✅ **Best for**: High-intent flows like authentication, referral links, and onboarding. + +--- + +
+ +
+ +## How it works + +When users tap a link — from a website, ad, QR code, or elsewhere — they launch a lightweight version of your Android app instantly. No Play Store. No install step. Just instant access. + +This allows you to: + +- Authenticate users quickly, using Rownd +- Capture user intent with minimal drop-off +- Seamlessly transition users to the full app after sign-in + +--- + +## Project structure + +To build an Instant App, your Android project must use a **modular** structure. + +### 🔹 Base module (`:base`) + +The base module includes shared code and resources used across your app, including your instant and installable experiences. This includes: + +- Shared layouts and assets +- Common logic/utilities +- The Rownd SDK (💡Keep it lean!) + +### 🔹 Feature modules + +Split your app into **feature modules** for each experience: + +| Module type | Purpose | Notes | +|-------------|---------|-------| +| `:instant-login` | The minimal experience for Rownd login | Must stay under 15MB total size | +| `:full-app` | The installable full version of your app | Can include everything | + +> ⚠️ **Google Play size limit**: Instant app experiences must be ≤15MB total (including the base module). Strip unused assets, fonts, and libraries. + +--- + +## Getting started + +### 1. Enable Instant Apps in your project + +Follow [Google’s official guide](https://developer.android.com/topic/google-play-instant) to set up: + +- Instant app support in your manifest +- `base`, `feature`, and `instant` module structure +- Instant app build variants + +### 2. Add Rownd to your instant feature + +Include the Rownd SDK in your `:base` module (or `:instant-login` if you want more separation). Follow the [Android SDK integration guide](/sdk-reference/mobile/android) to configure Rownd for sign-in. + +#### `settings.gradle` + +```groovy +include ':base', ':instant-login', ':full-app' +``` + +**base/build.gradle.kts** + +```kotlin +dependencies { + implementation("io.rownd:android:") + // other shared deps +} +``` + +```kotlin +class MainApplication : Application() { + override fun onCreate() { + super.onCreate() + + Rownd.configure( + this, + "REPLACE_WITH_YOUR_APP_KEY" + ) + } +} +``` + +#### `instant-login/build.gradle.kts` + +```kotlin +dependencies { + implementation(project(":base")) + implementation("io.rownd:android:") + // other instant app deps +} +``` + +```kotlin +class InstantLoginActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // Your instant app logic here + setContent { + InstantLoginScreen(onSignIn = { + Rownd.requestSignIn() + }) // Your instant app UI + } + } +} +``` + +### 3. Link to your instant experience + +You can generate smart links or deep links to launch your instant app directly from: +- Your website +- QR codes +- Marketing emails and campaigns + +Rownd can generate these links automatically, or you can create them manually using App Links. + +--- + +### Example use case + +A referral campaign sends users a personalized link. Instead of going to the Play Store, the user: +1. Launches your Instant App directly +2. Authenticates via Rownd (email, passkey, social, etc.) +3. Is optionally prompted to install the full app +4. Their session persists into the full app after install + +--- + +### Benefits +- Higher conversion: Fewer steps = more users signing in +- Lower bounce rate: No detour to the Play Store +- Seamless onboarding: Get users started before asking them to install + +--- + +Need help? + +If you’re planning to implement Instant Apps with Rownd, reach out to us — we’d love to help you get started or provide feedback on your module structure. diff --git a/rownd-docusaurus/docs/configuration/mobile/android.mdx b/rownd-docusaurus/docs/configuration/mobile/android.mdx new file mode 100644 index 0000000..f74392a --- /dev/null +++ b/rownd-docusaurus/docs/configuration/mobile/android.mdx @@ -0,0 +1,45 @@ +--- +title: "Android configuration" +sidebarTitle: "Configuration" +description: "Preparing Rownd to work with your Android app" +--- + +Configure Rownd for Android mobile devices including ([React Native](/sdk-reference/mobile/react-native) and [Flutter](/sdk-reference/mobile/flutter)). This configuration will allow multiple Rownd services to work in the Android operating system like [App Links](/configuration/mobile/overview#what-are-universal-links) and [Passkeys](/configuration/authentication-methods/passkeys). + +## Android App Links + +### 1. Configure the Rownd Platform + +1. Select **Sign-in methods** from the left navigation menu. +2. In the Sign-in preferences section, locate [**Mobile app settings**](/configuration/mobile/mobile-app-settings) +3. Fill out mobile app settings for Android + - Subdomain (e.g., myapp for myapp.rownd.link - the .rownd.link portion is added automatically). + - Play store URL - The direct link to your app in the Google Play Store + - Package name - The package name for your app as shown in the Google Play Console (e.g., `com.example.myapp`) + - SHA256 certificate fingerprints - For dev/test apps signed locally or manually, obtain the SHA256 hash from your keystore. For apps distributed through the Google Play Store that use automatic signing, obtain the SHA256 hash from the [Google Play Console](https://play.google.com/console/developers). +4. Ensure Android is **enabled** and hit **save** + +![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings.png) + +### 2. Configure your Android project + +Configure the `AndroidManifest.xml` file with an intent filter containing your `subdomain` + +```xml + + + + + + + + + + + + + +``` diff --git a/rownd-docusaurus/docs/configuration/mobile/ios-app-clip.mdx b/rownd-docusaurus/docs/configuration/mobile/ios-app-clip.mdx new file mode 100644 index 0000000..f7511a7 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/mobile/ios-app-clip.mdx @@ -0,0 +1,347 @@ +--- +title: "Using iOS App Clips" +sidebarTitle: "App Clips" +description: "100% conversion from web to native mobile app" +--- + +You can use Rownd's iOS SDK with its built-in understanding of App Groups to get users from web, to App Clip, to mobile app without losing users during conversion. Simply have users sign in from the App Clip. After they download the full app, they will already be signed in. + +
+ +
+ +This seamless authentication flow solves one of the biggest friction points in mobile user acquisition - requiring users to create new accounts or re-authenticate when transitioning between experiences. With Rownd: + +- Users can authenticate on your website +- Continue their journey in an App Clip with the same authenticated session +- Install the full app and find themselves already signed in and ready to go + +This creates a frictionless conversion funnel that significantly improves user retention and engagement by eliminating authentication barriers between platforms. + +You can reference an example using App Clips with Rownd in the official [Rownd iOS SDK GitHub repo](https://github.com/rownd/ios/tree/main/example/LandmarksAppClip). + +## How it works + +Rownd leverages Apple's App Groups technology to securely share authentication state between your App Clip and full application. This document provides clear, step-by-step guidance for integrating and configuring Rownd authentication within your App Clips and ensuring continuity to your main iOS application. + +The following steps assume you have already set up your App Clip; if you haven't done this yet, please skip to the [setting up app clips](#%F0%9F%93%B1-setting-up-app-clips) section below before proceeding with the Rownd integration. + +--- + +## 📦 Step 1: Add Rownd SDK dependencies + +Before configuring Rownd in your app and App Clip, you need to add the Rownd SDK as a dependency to both targets: + +### Using Swift Package Manager (Recommended) + +1. In Xcode, select **File → Add Packages...** +2. Enter the Rownd iOS SDK repository URL: `https://github.com/rownd/ios` +3. Select "Up to Next Major Version" for dependency rule +4. **Important:** Make sure to select BOTH your main app target AND your App Clip target: + - Your main app target (e.g., `YourApp`) + - Your App Clip target (e.g., `YourApp Clip`) + +### Using CocoaPods + +Alternatively, if your project uses CocoaPods, add Rownd to your Pod file: + +```ruby +# Your main app target +target 'YourApp' do + pod 'Rownd' +end + +# Your App Clip target +target 'YourApp Clip' do + pod 'Rownd' +end +``` + +Then run `pod install` in your terminal to install the dependencies. + +For more detailed information on installing and configuring the Rownd iOS SDK, refer to the [Rownd iOS SDK Documentation](https://docs.rownd.io/sdk-reference/mobile/ios). + +--- + +## 🔧 Step 2: Create separate AppDelegates + +Ensure both your **main app** and **App Clip** targets have separate, clearly linked `AppDelegate.swift` files. + +### Example: `AppDelegate.swift` + +Both your App Clip and Main App should initialize Rownd like this: + +```swift +import UIKit +import Rownd + +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + Task { + Rownd.config.appGroupPrefix = "com.example" // Replace with your app group prefix + await Rownd.configure( + launchOptions: launchOptions, + appKey: "REPLACE_WITH_YOUR_ROWND_APP_KEY" + ) + } + return true + } +} +``` + +### Common mistake: When using SwiftUI, be sure to link your `AppDelegate` in your main app's `App` struct: + +Ensure the following line explicitly links your AppDelegate: + +```swift +import SwiftUI + +@main +struct YourApp: App { + @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +--- + +## 🔗 Step 3: Configure App Groups + +Both your main app and App Clip must share the **exact same App Group identifier** for Rownd authentication continuity: + +### MUST USE the Rownd preset App Group identifier format: +``` +group..io.rownd.sdk +``` + +Example: +``` +group.com.your-app.io.rownd.sdk +``` + +Explicitly set this App Group in both: +- **Main App → Signing & Capabilities → App Groups** +- **App Clip → Signing & Capabilities → App Groups** + +--- + +## 📦 Step 4: Configure Rownd Dashboard + +Rownd explicitly relies on your **bundle identifiers**. You must explicitly list both your App Clip and Main App bundle identifiers in the Rownd Dashboard: + +**Example:** +- Main app: `com.yourapp.ios-demo` +- App Clip: `com.yourapp.ios-demo.Clip` + +Explicitly add both bundle IDs under your Rownd Dashboard **App Settings → Bundle IDs**. + +--- + +## 📋 Step 5: Set required capabilities and entitlements + +Explicitly ensure the following capabilities and entitlements are correctly configured: + +- ✅ **App Groups** (same identifier as above) +- ✅ **Associated Domains** (for universal linking) + ``` + applinks:your-domain.com + ``` +- ✅ **Parent Application Identifiers** (for App Clip → Main App linking) + +Manually set the [Parent Application Identifiers](https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.parent-application-identifiers) if missing: + +### Example (`.entitlements` file XML): +```xml +com.apple.developer.parent-application-identifiers + + com.yourapp.ios-demo + +``` + +--- + +## 🛠️ Step 6: Debugging & Common Issues + +### Issue: `x-rownd-app-key header is required` + +Indicates the Rownd SDK is not properly initialized. Confirm: + +- Explicit AppDelegate linking (Step 2). +- Proper App Groups set up (Step 3). +- Correct app keys and bundle IDs in Rownd Dashboard (Step 4). + +### Issue: Rownd Hub not loading + +- Ensure ATS (`App Transport Security`) settings temporarily allow arbitrary loads (testing only): +```xml +NSAppTransportSecurity + + NSAllowsArbitraryLoads + + +``` + +--- + +## 🚀 Final Checklist + +✅ **Separate AppDelegates explicitly linked** +✅ **App Groups correctly shared** +✅ **Bundle IDs registered explicitly on Rownd dashboard** +✅ **Capabilities and Entitlements correctly set** + +This structured configuration ensures seamless Rownd authentication across your main app and App Clips. + +--- + +## ✨ Best practices for App Clips with Rownd + +### 1. Use Smart Links for auto sign-in + +For a truly seamless experience, you can automatically sign in users using Smart Links that direct users to your App Clip. When transitioning an authenticated user from your website, redirect them using an authenticated Smart Link. Or, use Smart Links in directed communications to users to ensure they're signed in when they open your App Clip (and ultimately, your full app). + +### 2. Use explicit sign-up buttons + +Rather than forcing authentication immediately upon launch, provide a clear call-to-action that allows users to sign up when they're ready: + +```swift +Button("Sign up") { + Rownd.requestSignIn() +} +.buttonStyle(.borderedProminent) +.padding() +``` + +This approach respects user agency and creates a better first-time experience. + +### 3. Maintain UI consistency between your App Clip and main app + +Make your App Clip feel like a natural extension of your main app. Use the same: +- Color schemes and branding +- UI components and patterns +- Typography and visual language +- Terminology and navigation patterns + +This creates a seamless transition when users move from the App Clip to your full app, reinforcing that they're already familiar with your product. + +### 4. Focus on a single, core task + +App Clips should concentrate on delivering one specific feature quickly: +- Identify the most valuable single action for new users +- Remove all UI elements not directly supporting this core action +- Keep the App Clip under 10MB (smaller is better for faster loading) +- Design the authentication flow to support this core task with minimal friction + +### 5. Design strategic, full app installation prompts + +Time your prompts for installing the full app strategically: +- Wait until after users complete their core task +- Highlight additional features available in the full app +- Emphasize that they'll remain signed in when transitioning +- Use Apple's App Clip API to show the installation card: + +```swift +// UIKit: After user completes primary task +guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return } + +let config = SKOverlay.AppClipConfiguration(position: .bottom) +let overlay = SKOverlay(configuration: config) +overlay.present(in: scene) +``` + + +For SwiftUI, you can also use the [`.appStoreOverlay` modifier](https://developer.apple.com/documentation/swiftui/view/appstoreoverlay(ispresented:configuration:)) to present the App Clip card: + + +--- + +## 📱 Setting up App Clips + +Before integrating Rownd authentication with your App Clip, you'll need to properly set up the App Clip itself. This process requires configuration across multiple platforms: + +### Xcode Configuration +- Create an App Clip target in your existing iOS app project +- Configure the App Clip's `Info.plist` with required entries +- Set up App Clip experience metadata + +### Parent-child relationship configuration + +A critical aspect of App Clips is establishing the proper parent-child relationship between your main app and App Clip: + +#### For the App Clip (child): +Add the parent application identifier entitlement to your App Clip's `entitlements` file: +```xml +com.apple.developer.parent-application-identifiers + + $(AppIdentifierPrefix)com.yourcompany.yourapp + +``` + +#### For the main app (parent): +Add the associated App Clip identifier entitlement to your main app's `entitlements` file: +```xml +com.apple.developer.associated-appclip-app-identifiers + + $(AppIdentifierPrefix)com.yourcompany.yourapp.Clip + +``` + +This bidirectional relationship is essential for: +- Proper App Store presentation +- Authentication state transfer +- App Clip to full app conversion tracking + +### App Clip Codes & Launch Experience + +App Clip Codes provide an intuitive way for users to discover and launch your App Clip in the physical world: + +- **App Clip Codes**: Custom-designed scannable codes that can be placed on physical materials +- **NFC tags**: For contactless launch of your App Clip +- **QR codes**: For camera-based scanning and launch +- **Safari App Banner**: Present an App Clip card when users visit your website +- **Maps integration**: Allow discovery through Apple Maps (if applicable) + +The launch experience is critically important - when a user activates an App Clip: +1. A lightweight App Clip card appears with basic app information +2. User taps "Open" to launch without installation +3. App Clip loads with contextual data from the invocation method +4. Rownd authentication can happen seamlessly at this point + +### Apple Developer Portal Configuration +- Configure App ID for your App Clip +- Set up appropriate provisioning profiles +- Enable necessary entitlements + +### App Store Connect Configuration +- Set up App Clip card metadata +- Configure invocation methods (QR codes, NFC tags, links) +- Submit for review alongside your main app + +Setting up App Clips properly requires significant effort and attention to detail across all these platforms. We recommend thoroughly reviewing Apple's official documentation before proceeding with the Rownd integration steps outlined in this guide. + +For complete details on setting up App Clips, refer to: +- [Apple's App Clip documentation](https://developer.apple.com/documentation/appclip) +- [Associated App Clip App Identifiers documentation](https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.associated-appclip-app-identifiers) +- [App Clip Codes documentation](https://developer.apple.com/documentation/app_clips/creating_app_clip_codes) + +--- + +## 📖 References + +- [Rownd SDK iOS documentation](https://docs.rownd.io/sdk-reference/mobile/ios#usage-within-app-extensions) +- [Apple App Clip documentation](https://developer.apple.com/documentation/appclip) +- [Associated App Clip App Identifiers documentation](https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.associated-appclip-app-identifiers) +- [Creating App Clip Codes documentation](https://developer.apple.com/documentation/app_clips/creating_app_clip_codes) diff --git a/rownd-docusaurus/docs/configuration/mobile/ios.mdx b/rownd-docusaurus/docs/configuration/mobile/ios.mdx new file mode 100644 index 0000000..054f7b6 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/mobile/ios.mdx @@ -0,0 +1,47 @@ +--- +title: "iOS configuration" +sidebarTitle: "Configuration" +description: "Preparing your iOS app to work with Rownd" +--- + +Configure Rownd for iOS mobile devices including ([React Native](/sdk-reference/mobile/react-native) and [Flutter](/sdk-reference/mobile/flutter)). This configuration will allow multiple Rownd services to work in the iOS operating system like [Universal Links](/configuration/mobile/overview#what-are-universal-links) and [Passkeys](/configuration/authentication-methods/passkeys). + +### 1. Configure in Rownd Platform + +1. Select **Sign-in methods** from the left navigation menu. +2. In the Sign-in preferences section, locate [**Mobile app settings**](/configuration/mobile/mobile-app-settings) +3. Fill out mobile app settings for iOS + - Subdomain (e.g., myapp for myapp.rownd.link - the .rownd.link portion is added automatically). + - App store URL - The direct link to your app in the Apple App Store + - Bundle IDs - A comma-separated list of bundle IDs for your app (e.g., `com.example.myapp`) + - Team ID - The team ID for your app as shown in the [Apple Developer Portal](https://developer.apple.com/account) (e.g., `15GKOXA3H6`) +4. Ensure iOS is **enabled** and hit **save** + +![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings.png) + +### 2. Configure in project (Xcode or entitlements file) + +#### Using Xcode + +1. In your Xcode project, select your app from the left, then navigate to Targets > Signing & Capabilities +2. Add Associated Domains as a capability +3. Add the subdomain to the applinks entitlement. `applinks:.rownd.link` + +![Configuring mobile apps only takes a few minutes.](/images/xcode-deep-link.png) + +#### Using entitlements file + +file: `ios/[appName]/[appName].entitlement` + +```xml + + + ... + com.apple.developer.associated-domains + + ... + subdomain.rownd.link + + + +``` diff --git a/rownd-docusaurus/docs/configuration/mobile/mobile-app-settings.mdx b/rownd-docusaurus/docs/configuration/mobile/mobile-app-settings.mdx new file mode 100644 index 0000000..43d0aa2 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/mobile/mobile-app-settings.mdx @@ -0,0 +1,46 @@ +--- +title: "Mobile app settings" +sidebarTitle: "Mobile app settings" +description: "Configuring your mobile app" +--- + +Configure mobile app settings to enable a prompt for mobile users to download the app or take them to their existing app. + +### Configure iOS mobile app settings + +1. App store URL + 1. Log in to [Apple App Store Connect](https://appstoreconnect.apple.com/apps). + 2. Go to My Apps and click on you app. + 3. Click App Information in the General section. + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-app-info.png) + 4. Click View on App Store in the Additional Information section. + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-apple-store-url.png) + 5. Copy the URL of the page. +2. Bundle IDs + 1. Enter a comma-separated list of bundle IDs for your app (e.g., `com.example.myapp`) +3. Team ID + 1. Log in to Apple [Apple Developer Portal](https://developer.apple.com/account) + 2. Scroll down to Membership details + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-ios-team-id.png) + 3. Copy the Team ID + +### Configure Android mobile app settings + +1. Play store URL + 1. Log in to [Google Play Console](https://play.google.com/console) + 2. Select your app from the dashboard. + 3. Click on View on Google Play. + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-google-store-url.png) + 4. Copy the URL of the page. +2. Package name + 1. Log in to [Google Play Console](https://play.google.com/console) + 2. Select your app from the dashboard. + 3. Copy package name from the app dashboard + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-google-package-name.png) +3. SHA-256 Cert Fingerprints + 1. Log in to [Google Play Console](https://play.google.com/console) + 2. Select your app from the dashboard. + 3. Click App Integrity under the Release section then click Settings in the Play app signing section. + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-app-integrity.png) + 4.Copy SHA-256 certificate fingerprint in the App signing key certificate section + ![Configuring mobile apps only takes a few minutes.](/images/mobile-app-settings-sha256.png) diff --git a/rownd-docusaurus/docs/configuration/mobile/overview.mdx b/rownd-docusaurus/docs/configuration/mobile/overview.mdx new file mode 100644 index 0000000..383c9e4 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/mobile/overview.mdx @@ -0,0 +1,84 @@ +--- +title: "Mobile app configuration" +sidebarTitle: "Overview" +description: "Configure mobile apps in Rownd with ease." +--- + +## On this page + +- [Introduction to Mobile App Configuration](#introduction-to-mobile-app-configuration) +- [What Are Universal Links?](#what-are-universal-links) +- [Submitting Your App for Review](#submitting-your-app-for-review) +- [Configure by Platform](#configure-by-platform) + - [iOS Configuration](/configuration/mobile/ios) + - [Android Configuration](/configuration/mobile/android) + +## Introduction to Mobile App Configuration + +Rownd makes it easy to add secure, seamless sign-in to your mobile app. Whether you're building with [React Native](/sdk-reference/mobile/react-native), [Flutter](/sdk-reference/mobile/flutter), or [native iOS](/sdk-reference/mobile/ios)/[Android](/sdk-reference/mobile/android), our mobile SDKs allow you to integrate modern authentication experiences without the complexity. + +Once the SDK is set up, you can enable features like universal Sign-in Links — which automatically direct users to your app and sign them in without needing a password. + +This guide will walk you through how Rownd works with mobile platforms, how to prepare your app for App Store review, and how to configure your mobile SDK for iOS and Android. + + +### What are universal links? +Universal links are a type of deep link that allows users to open your mobile app directly from a URL. If the app is installed, the link takes the user straight to the app. If not, it redirects them to the appropriate app store (Apple App Store or Google Play). + +Rownd uses universal links as part of its Sign-in flow, helping users sign in seamlessly with a single tap — no password required. + +- **Simplified user experience** - By directing users to the relevant content or app store, universal links create a more streamlined and intuitive user journey, which can lead to increased user engagement and retention. +- **Improved conversion rates** - By reducing friction in the user experience and lowering the barriers to entry, universal links can help boost conversion rates for app installations that lead to user sign-ups. +- **Enhanced security** - Universal links are more secure than legacy custom URL schemes, as they rely on the app's domain and can only be used by the associated app, thus reducing the risk of phishing attacks or unauthorized access. + +Universal links reduce friction and improve conversion by making sign-in feel like magic — no extra steps, no lost users. + + +A [Rownd Mobile SDK](/sdk-reference/mobile) must be installed in your app to use this feature. + + +### Submitting Your App for Review + +When submitting your app to the App Store or Google Play Store, reviewers will need a way to access and test the app. If you're using Rownd for authentication, you can streamline this process by setting up simple test accounts. + +**Recommended Setup** + +Use a disposable email inbox service like [Mailinator](https://www.mailinator.com) to create one or more test accounts. + +**Example:** + +- Test email address: my-app-review-1@mailinator.com + +- Instruct reviewers to: + 1. Enter the test email in your app’s sign-in screen + 2. Visit the corresponding Mailinator inbox at: + ``` + https://www.mailinator.com/v4/public/inboxes.jsp?to=my-app-review-1 + ``` + +You can create multiple test accounts by incrementing the address (e.g., `my-app-review-2@mailinator.com`, etc.). + +> Be sure the inbox name matches the email address +> (e.g., `my-app-review-1@mailinator.com` → `my-app-review-1` inbox on Mailinator). + +**Optional Enhancements** + +- Preload test data into the accounts +- Use conditional logic in your app to streamline or skip onboarding for known test users + +This approach works for both iOS (App Store) and Android (Google Play), and is commonly accepted during the review process. + + + +### Configure by platform + +See our step-by-step configuration guides for [iOS](/configuration/mobile/ios) and [Android](/configuration/mobile/android) for assistance in filling out this section. + + + + Configure mobile for iOS including React Native and Flutter + + + Configure mobile for Android including React Native and Flutter + + diff --git a/rownd-docusaurus/docs/configuration/oidc/app-key-oidc-1.png b/rownd-docusaurus/docs/configuration/oidc/app-key-oidc-1.png new file mode 100644 index 0000000..7d2be46 Binary files /dev/null and b/rownd-docusaurus/docs/configuration/oidc/app-key-oidc-1.png differ diff --git a/rownd-docusaurus/docs/configuration/oidc/configure-oidc.png b/rownd-docusaurus/docs/configuration/oidc/configure-oidc.png new file mode 100644 index 0000000..d930131 Binary files /dev/null and b/rownd-docusaurus/docs/configuration/oidc/configure-oidc.png differ diff --git a/rownd-docusaurus/docs/configuration/oidc/customize-screen-oidc.png b/rownd-docusaurus/docs/configuration/oidc/customize-screen-oidc.png new file mode 100644 index 0000000..d7a387f Binary files /dev/null and b/rownd-docusaurus/docs/configuration/oidc/customize-screen-oidc.png differ diff --git a/rownd-docusaurus/docs/configuration/oidc/details-oidc.png b/rownd-docusaurus/docs/configuration/oidc/details-oidc.png new file mode 100644 index 0000000..5f493f4 Binary files /dev/null and b/rownd-docusaurus/docs/configuration/oidc/details-oidc.png differ diff --git a/rownd-docusaurus/docs/configuration/oidc/overview.mdx b/rownd-docusaurus/docs/configuration/oidc/overview.mdx new file mode 100644 index 0000000..4fa4823 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/oidc/overview.mdx @@ -0,0 +1,462 @@ +--- +title: "OpenID Connect Setup" +sidebarTitle: "Overview" +--- + +## Table of Contents + +1. [Set up using the platform](#using-the-rownd-platform) + +2. [Setup using the API](#using-the-api) + - [Required headers](#required-headers) + - [API endpoints](#api-endpoints) + - [OIDC configuration discovery](#oidc-configuration-discovery) + - [OIDC endpoints](#oidc-endpoints) + - [Response format](#response-format) + - [Logo management](#uploading-oidc-client-logos) + - [Upload requirements](#required-headers-1) + - [Logo parameters](#parameters) + - [Advanced configuration](#advanced-configuration) + - [Custom interaction endpoint](#custom-interaction-endpoint) + - [User flow example](#user-flow-example) + + +### Using the Rownd Platform + +You can set up an OIDC client directly through the [Rownd platform](https://app.rownd.io): + +**1. Navigate to your application** + +**2. Open the "App Keys" page on the left menu and click on the "OIDC Clients" tab** + +![OIDC Clients](app-key-oidc-1.png) + +**3. Click "Create New OIDC Client"** + +**4. Set your OIDC client details** + + + +![OIDC Clients](details-oidc.png) + + +#### Fields +- **Name**: A display name for your OIDC client (required) +- **Redirect URIs**: Where users will be redirected after authentication (required). You can add more than one. + - Example: `https://example.com/callback` +- **Allowed Scopes**: The scopes that the OIDC client is allowed to request. You can add more than one. + - Example: `openid profile email` ; note; you can add additional date fields to Rownd for more finite scopes. + +Click "Next" + +**5. Retrieve client credentials and OpenID endpoints** +You can now retrieve your client credentials and use them to configure your OIDC client. You can also see the OIDC endpoints. + + +Make sure to save your client credentials (client_id and secret) after creation, as the secret cannot be retrieved later. + + +![OIDC Clients](configure-oidc.png) + +**6. OIDC customizations** + +Click on "Customizations" to customize sign-in and consent modals with a call to action and logos that help your users stay in context. + +![OIDC Clients](customize-screen-oidc.png) + + +### Using the API + +To create or update an OIDC client configuration via the API, you'll need your Rownd application credentials. + +#### Required headers +| Header | Description | +|--------|-------------| +| `x-rownd-app-key` | Your Rownd application key | +| `x-rownd-app-secret` | Your Rownd application secret | + +#### API endpoints +- Create: `POST https://api.rownd.io/applications/{app-id}/oidc-clients` +- Update: `PUT https://api.rownd.io/applications/{app-id}/oidc-clients/{client-id}` + +#### cURL Example + +```bash +# Create new OIDC client +curl -X POST 'https://api.rownd.io/applications/{app-id}/oidc-clients' \ +-H 'x-rownd-app-key: YOUR_APP_KEY' \ +-H 'x-rownd-app-secret: YOUR_APP_SECRET' \ +-H 'Content-Type: application/json' \ +-d '{ + "name": "Example OIDC Provider", + "description": "Example OIDC Provider", + "config": { + "allowed_origins": [ + "https://example.com" + ], + "redirect_uris": [ + "https://example.com/callback" + ], + "post_logout_uris": [ + "https://example.com/logout" + ], + "logo_uri": "https://storage.rownd.io/logo-example.png", + "logo_dark_mode_uri": "https://storage.rownd.io/logo-dark-example.png" + } +}' + +# Update existing OIDC client +curl -X PUT 'https://api.rownd.io/applications/{app-id}/oidc-clients/{client-id}' \ +-H 'x-rownd-app-key: YOUR_APP_KEY' \ +-H 'x-rownd-app-secret: YOUR_APP_SECRET' \ +-H 'Content-Type: application/json' \ +-d '{ + "name": "Updated OIDC Provider", + "description": "Updated OIDC Provider", + "config": { + "allowed_origins": [ + "https://example.com" + ], + "redirect_uris": [ + "https://example.com/callback" + ], + "post_logout_uris": [ + "https://example.com/logout" + ], + "logo_uri": "https://storage.rownd.io/logo-example.png", + "logo_dark_mode_uri": "https://storage.rownd.io/logo-dark-example.png" + } +}' +``` + + +Replace `YOUR_APP_KEY`, `YOUR_APP_SECRET`, and `{app-id}` with your actual Rownd application credentials and ID. For the update request, also replace `{client-id}` with your OIDC client ID. + + +## Configuration + +Refer to the [Rownd OpenID Connect API documentation](/api-reference/oidc/clients) for detailed information on creating and managing OpenID clients. + +To create a new OIDC client configuration, send a POST request to `api.rownd.io/applications/{app-id}/oidc-clients` with the following body parameters: + +### Request Body Parameters + +| Parameter | Description | +|-----------|-------------| +| `name` | The display name of your OIDC client | +| `description` | A brief description of your OIDC client | +| `config.allowed_origins` | Array of allowed origins that can make requests to the OIDC server | +| `config.redirect_uris` | Array of valid URIs where users will be redirected after authentication | +| `config.post_logout_uris` | Array of valid URIs where users will be redirected after logging out | +| `config.logo_uri` | URL to the logo image used in light mode | +| `config.logo_dark_mode_uri` | URL to the logo image used in dark mode | + +### Example Request + +```json +{ + "name": "Example OIDC Provider", + "description": "Example OIDC Provider", + "config": { + "allowed_origins": [ + "https://example.com" + ], + "redirect_uris": [ + "https://example.com/callback" + ], + "post_logout_uris": [ + "https://example.com/logout" + ], + "logo_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png", + "logo_dark_mode_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png" + } +} +``` + +### Response Format + +Both POST and PUT requests will return a response with the following structure: + +```json +{ + "id": "oidc_client_ck9c1glf0100001l2f7z8z9z9", + "app_id": "app_ckl8bcf1g000001l2f7z8z9z9", + "name": "Example OIDC Provider", + "description": "Example OIDC Provider", + "config": { + "allowed_origins": [ + "https://example.com" + ], + "redirect_uris": [ + "https://example.com/callback" + ], + "post_logout_uris": [ + "https://example.com/logout" + ], + "logo_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png", + "logo_dark_mode_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png" + }, + "created_at": "2024-12-05T23:34:05.709Z", + "updated_at": "2024-12-05T23:34:05.709Z", + "credentials": [ + { + "name": "Production API Key", + "client_id": "string", + "secret": "string", + "expires": "2024-12-31T23:59:59Z", + "application": "app_k3y1qwerty12345", + "app_variant_id": "variant_fgy1qw367fty121lm", + "oidc_client_configuration_id": "oidcc_k3y1qwerty12345", + "created_at": "2024-12-05T23:34:05.709Z", + "updated_at": "2024-12-05T23:34:05.709Z" + } + ] +} +``` + +### Response Fields + +| Field | Description | +|-------|-------------| +| `id` | Unique identifier for the OIDC client configuration | +| `app_id` | The Rownd application ID this configuration belongs to | +| `name` | Display name of the OIDC client | +| `description` | Description of the OIDC client | +| `config` | Configuration object containing origins, URIs, and logos | +| `created_at` | Timestamp of when the configuration was created | +| `updated_at` | Timestamp of the last update | +| `credentials` | Array of credential objects containing authentication details | + +#### Credentials Object + +| Field | Description | +|-------|-------------| +| `name` | Name of the credential | +| `client_id` | The OIDC client ID to use for authentication | +| `secret` | The client secret to use for authentication | +| `expires` | Expiration date of the credentials | +| `application` | Associated Rownd application ID | +| `app_variant_id` | Variant ID if applicable | +| `oidc_client_configuration_id` | ID of the OIDC client configuration | +| `created_at` | Timestamp of when the credentials were created | +| `updated_at` | Timestamp of the last credentials update | + + +Store the `client_id` and `secret` securely as they will be needed for all subsequent OIDC operations. + + +## OpenID Configuration Discovery + +Rownd provides a standard OpenID Configuration discovery endpoint that returns a complete list of OIDC specifications and endpoints for your application. + +### Discovery Endpoint + +```http +GET api.rownd.io/oidc/{app_id}/.well-known/openid-configuration +``` + +Replace `{app_id}` with your Rownd application ID to get the complete OIDC configuration for your app. For example: +``` +https://api.rownd.io/oidc/app_wj43asd4ywn790plclbhux6a/.well-known/openid-configuration +``` + +This endpoint returns a JSON document containing all supported OIDC features, endpoints, and capabilities of your Rownd OIDC server, following the OpenID Connect Discovery specification. + + +The discovery endpoint is publicly accessible and does not require authentication. It's commonly used by OIDC clients to automatically configure themselves. + + +## OpenID Endpoints + +Rownd provides three main OIDC endpoints, all accessible at `https://api.rownd.io/oidc/{app-id}/`: + +### 1. Authorization Endpoint (`/auth`) +- Used to authenticate users and obtain authorization +- Initiates the authentication flow +- Returns an authorization code that can be exchanged for tokens +- Supports standard OIDC parameters like `scope`, `response_type`, and `redirect_uri` + +### 2. Token Endpoint (`/token`) +- Exchanges authorization codes for access and ID tokens +- Supports refresh token requests +- Requires client authentication using client_id and client_secret +- Returns JWT tokens containing user information and access rights + +### 3. UserInfo Endpoint (`/me`) +- Provides detailed information about the authenticated user +- Requires a valid access token +- Returns user profile data based on the granted scopes +- Supports standard OIDC claims + +## Credentials + +After creating an OIDC client configuration, you'll receive credentials in the response: + +- `client_id`: Your unique client identifier +- `client_secret`: Your client secret for secure communication + + +Store your client_secret securely! It cannot be recovered if lost and would require generating new credentials. + + +## Implementation Flow + +1. Configure your OpenID client using the configuration endpoint +2. Store the returned client_id and client_secret securely +3. Implement the authorization flow: + - Direct users to the `/auth` endpoint for authentication + - Handle the callback with the authorization code + - Exchange the code for tokens at the `/token` endpoint + - Fetch user information from the `/me` endpoint as needed + +## Example Implementation + +```javascript +// Example authorization request +const authUrl = `https://api.rownd.io/oidc/${appId}/auth?` + + `client_id=${clientId}&` + + `redirect_uri=${encodeURIComponent(redirectUri)}&` + + `response_type=code&` + + `scope=openid profile email`; + +// Redirect user to authUrl + +// After receiving the authorization code in your callback: +async function exchangeCode(code) { + const response = await fetch(`https://api.rownd.io/oidc/${appId}/token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code, + client_id: clientId, + client_secret: clientSecret, + redirect_uri: redirectUri, + }), + }); + + return await response.json(); +} +``` + +## Best Practices + +1. Always use HTTPS for redirect URIs +2. Implement proper token storage and refresh mechanisms +3. Validate all tokens on your backend +4. Keep your client_secret secure and never expose it in client-side code +5. Implement proper error handling for all OIDC endpoints + +Need help? Contact our [support team](mailto:support@rownd.io) for assistance with your OIDC implementation. + +### Uploading OpenID Client Logos + +You can upload custom logos for your OIDC client that will be displayed in light and dark modes. Logos can be uploaded using the following API endpoint. + +#### Logo Upload Endpoint + +```http +PUT /application/{app-id}/oidc_clients/{client-id}/logo/{type} +``` + +#### Parameters +| Parameter | Description | +|-----------|-------------| +| `app` | Your Rownd application ID | +| `client` | Your OIDC client ID | +| `type` | Either 'light' or 'dark' for the respective display modes | + +#### Required Headers +| Header | Description | +|--------|-------------| +| `x-rownd-app-key` | Your Rownd application key | +| `x-rownd-app-secret` | Your Rownd application secret | +| `x-rownd-filename` | The filename of your logo | + + +Only PNG and SVG file formats are supported for logo uploads. + + +#### cURL Example + +```bash +# Upload light mode logo +curl -X PUT 'https://api.rownd.io/application/{app-id}/oidc_clients/{client-id}/logo/light' \ +-H 'x-rownd-app-key: YOUR_APP_KEY' \ +-H 'x-rownd-app-secret: YOUR_APP_SECRET' \ +-H 'x-rownd-filename: logo.png' \ +-H 'Content-Type: image/png' \ +--data-binary '@/path/to/your/logo.png' + +# Upload dark mode logo +curl -X PUT 'https://api.rownd.io/application/{app-id}/oidc_clients/{client-id}/logo/dark' \ +-H 'x-rownd-app-key: YOUR_APP_KEY' \ +-H 'x-rownd-app-secret: YOUR_APP_SECRET' \ +-H 'x-rownd-filename: logo-dark.svg' \ +-H 'Content-Type: image/svg+xml' \ +--data-binary '@/path/to/your/logo-dark.svg' +``` + + +Ensure your logo files meet the following requirements: +- File format: PNG or SVG only +- Recommended dimensions: At least 512x512 pixels for optimal display +- File size: Keep files under 5MB for best performance + + +### Advanced configuration + +#### Custom interaction endpoint + +By default, OpenID authentication flows direct users to a Rownd-hosted URL for sign-in. However, if you have Rownd integrated into your website or application, you can provide a custom interaction endpoint for a more streamlined experience. + +When configured, users will be directed to your site/app instead of the default Rownd URL. This provides several benefits: +- Maintains your branded experience +- Leverages existing user sessions +- Reduces authentication steps when users are already logged in +- Provides a more seamless OIDC consent flow + +##### Configuration + +Add the `interaction_endpoint` to your OIDC client configuration under the `config` object: + +```json +{ + "name": "Example OIDC Provider", + "description": "Example OIDC Provider", + "config": { + "allowed_origins": [ + "https://example.com" + ], + "redirect_uris": [ + "https://example.com/callback" + ], + "post_logout_uris": [ + "https://example.com/logout" + ], + "interaction_endpoint": "https://example.com/auth", + "logo_uri": "https://storage.rownd.io/logo-example.png", + "logo_dark_mode_uri": "https://storage.rownd.io/logo-dark-example.png" + } +} +``` + + +The interaction endpoint must be a page where the Rownd JavaScript snippet is properly installed and configured (a single-page app like React will also work). This ensures the authentication flow can properly handle the OpenID consent process. + + +##### User flow example + +1. User initiates OIDC sign-in from a third-party application +2. Instead of going to `hub.rownd.io`, they are redirected to your custom endpoint (e.g., `https://example.com/auth`) +3. If the user is already signed in on your site: + - They only need to approve the OIDC consent + - No additional authentication is required +4. If the user is not signed in: + - They'll see your normal Rownd authentication flow + - After signing in, they'll be prompted for OIDC consent +5. After consent, they are redirected back to the original application + +This approach can significantly reduce friction in the authentication process, especially for users who frequently interact with your platform. diff --git a/rownd-docusaurus/docs/configuration/overview.mdx b/rownd-docusaurus/docs/configuration/overview.mdx new file mode 100644 index 0000000..0adbe1c --- /dev/null +++ b/rownd-docusaurus/docs/configuration/overview.mdx @@ -0,0 +1,38 @@ +--- +title: "Configuration" +sidebarTitle: "Overview" +description: + "The Rownd platform gives everything you need to add customizable + authentication to your product" +--- + +Rownd provides an out-of-the-box configuration allowing you to deploy frictionless authentication into your product in minutes. However, we know that your users have unique expectations that affect how they think about authentication. Some are technically-minded and will consciously pick a specific sign-in method while others will simply press the default or select whatever seems simplest. + +Rownd makes it easy to adjust your sign-in experience for what best fits your user-base. Rownd also dynamically tweaks the sign-in flow per user based on the their device, browser, and behaviors. + +You can adjust your product's sign-in experience in the following ways: + + + + + + + + + + + + +![](/images/configuration.png) diff --git a/rownd-docusaurus/docs/configuration/user-accounts/groups.mdx b/rownd-docusaurus/docs/configuration/user-accounts/groups.mdx new file mode 100644 index 0000000..18eac33 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/user-accounts/groups.mdx @@ -0,0 +1,87 @@ +--- +title: "User groups" +sidebarTitle: "User groups" +--- + +## What are Groups? + +Groups allow you to segment users within your application. You can manage groups as an administrator through the Rownd +Platform or programmatically through the [Group APIs](/api-reference/groups/overview). You can even allow users to create and manage their own groups. Once added to a group, users can be assigned roles to give them certain permissions +within the group. + + +![Rownd groups](/images/groups-1-list.png) + + +## Why Use Groups? + +- **Collaborations**: Suitable for apps promoting user collaboration or shared account spaces. Users can invite others or create new groups within your app. + +- **Role-Based Access**: Add users to a group and assign them specific roles. Check their role withini a group to enforce role-based access control. + +## How it works +1. From the "Users" tab in the Rownd platform, go to the "Groups" tab to view, manage, and add groups. + +2. Add a group: Use the "add" dropdown button from the groups tab and click "add new group." Name your group and determine whether an invitation is required to join. Open groups are suitable for public roles, while invitation-required groups are better for private roles. + + +![Add a new group](/images/add-new-group.png) + + +4. After adding a group, click "view" to see its contents and members. + + +![Add a new group](/images/single-group-view.png) + + +5. Add users manually or use Rownd APIs to integrate the invite flow into your app. Provide an email or phone number, select the member's role, and include a redirect URL for the user. + +Currently, you can only add one user at a time from the Rownd platform. + + +![Add a new group](/images/add-group-user.png) + + +6. After adding a member, copy the provided invite link. For now, you'll need to send this link to users via email, SMS, or some other means yourself. We will soon send this invite automatically for you. + + +![Add a new group](/images/copy-group-invite-link.png) + + +7. Manage members from the group’s page. All users in all groups will appear in the "users" table in the users tab on the platform. Once a user becomes part of a group, that group will appear in their Rownd account. + + +![Add a new group](/images/group-one-member.png) + + +8. To delete a group from the platform, either use the trash icon in the group line item in the groups table or press “Delete this group” from the specific group’s page. + +9. Edit a group name by clikcing on the 'Edit' icon on the card under your Group's name in a group page. + + +## Rownd Groups API Commands + +Go check out the [Group APIs](/api-reference/groups/overview) to get started integrating groups into your app + +## Coming Soon + +**Groups UI** +We will soon add support for managing groups, members, and invites through Rownd-provided user interfaces available in all of our SDKs. + +**Groups SDK Support** +Full support for group management is rolling out soon for all of our SDKs. + + +Note: The Groups feature is currently in beta. Your feedback at support@rownd.io is highly appreciated. + + +
+ +
diff --git a/rownd-docusaurus/docs/configuration/user-accounts/overview.mdx b/rownd-docusaurus/docs/configuration/user-accounts/overview.mdx new file mode 100644 index 0000000..8e5fc12 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/user-accounts/overview.mdx @@ -0,0 +1,22 @@ +--- +title: "User Accounts" +sidebarTitle: "Overview" +description: + "The Rownd platform gives everything you need to add instant sign in and profiles to your app" +--- + +Rownd offers instant user profiles through the Rownd Hub, as well as comprehensive [user management](./platform-user-table) in the **Users** tab within the platform. Additionally, with Rownd's [progressive profiles](./progressive-profiles), your users can explore your platform without the need for immediate sign-in, enhancing their experience. + +Discover more about user account options below: + + + + + + + + + + + ![Manage users from the users table in the Rownd platform](/images/Users-table.png) + \ No newline at end of file diff --git a/rownd-docusaurus/docs/configuration/user-accounts/platform-user-table.mdx b/rownd-docusaurus/docs/configuration/user-accounts/platform-user-table.mdx new file mode 100644 index 0000000..6ccb573 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/user-accounts/platform-user-table.mdx @@ -0,0 +1,109 @@ +--- +title: "Platform users table" +--- + +Unlike other authentication platforms, Rownd provides an intelligent, customizable user profile system. This allows you to collect information about your users, and use it to personalize their experience. It also enables Rownd to handle more of the personalization for you, integrate with other tools you might use, and enforce rules about who can access or update profile data. + +We provide a number of built-in fields, but you can also create your own custom fields. You can also customize whether fields are "owned" by the end-user or by your app, which limits who can modify data in the field. + +### Managing the profile schema + +Rownd configures some commonly used profile fields when an app is first created, but you can add to them, modify them, or remove them as needed. + +To manage the profile schema, open the [Rownd dashboard](https://app.rownd.io) and select **Data types** from the side navigation. + + +![Manage and edit the profile schema from the data types tab.](/images/data-types-tab.png) + + +#### Schema field options + +When adding or editing a field, the following options are available: + +- **Data type** - This is the name for the field that will be returned in programmatic operations (e.g., REST API responses). This is also used as the display name if one is not explicitly specified. This should be primarily machine-friendly (e.g., `first_name`) +- **Display name** - This is the name that will be displayed to end-users. If not specified, the "data type" will be used. +- **Type** - This is the data type for the field. The following types are available: + - **String** - Accepts any text. + - **Number** - A numeric value. + - **Boolean** - A `true/false` value. + - **Image** - A binary blob representing an image. Represented as a URL in API responses. + - **Document** - A binary blob representing a document (e.g., PDF, DOC, etc). Represented as a URL in API responses. + - **Date** - A date value. + - **Object** - A flexible, schema-less JSON object (e.g., `{ "foo": "bar" }`). + - **Any** - Makes no assumptions about the data stored--could be anything. +- **Required retention** - Sets the amount of time that data in the field must be retained. This is useful for fields that are required by law (e.g., GDPR requires that data be retained for 6 years). If not specified, data can be removed by the user at any time. _(Note: It is recommended to use this field only when absolutely necessary.) +- **Data owner** - Specifies who owns the data in the field. If set to **User**, the end-user can modify the data in the field. If set to **Application**, the end-user can only view the data in the field, and the app is responsible for updating it. +- **Visibility** (only applicable when "Data owner" is set to "Application") - Specifies who can view the data in the field. **Visible to users** indicates that the data is visible to the end-user in their profile. **Hidden from users** indicates that the data is only visible to the app when making server-to-server API requests (i.e., the app secret is present). + + +#### Adding a new field + +1. On the data types page, press **Add data type**. +2. From the **Data type** dropdown, select a built-in field or begin typing. If the field you want isn't in the list, you can create a custom field by typing in the desired name. +3. Complete the rest of the form as desired (see [schema field options](#schema-field-options) for details). +4. Press **Add** to save the new field. + +
+ +#### Editing an existing field + +1. On the data types page, locate the field you want to edit and click the three-dots icon on the right side of the table. Select **Edit** from the menu. +2. Make any desired changes to the field (see [schema field options](#schema-field-options) for details) on the available options. +3. Press **Save** to persist the changes and close the dialog. + + +#### Deleting a field + +1. On the data types page, locate the field you want to edit and click the three-dots icon on the right side of the table. Select **Delete** from the menu. +2. In the resulting dialog, verify that you are deleting the correct field, then press **Delete** to confirm. + +Deleting a field from the schema does not automatically remove data for that field in each user's profile; however, it will be missing from any API responses. + +Regardless, be careful that you don't have code that depends on the presence of this field. + + + +#### Managing users + +In the **Users** area of the platform, you have complete control over your users' profile information. Each time a user signs in, they are listed in the Users table. This table allows you to easily locate users, provide support, and manually edit their accounts. It provides information about the sign-in methods they have used and the profile information they have added. Additionally, you can utilize the filtering and sorting tools--located in the top right icons of the table--to efficiently navigate and organize the table. + + +![Manage users from the users table in the Rownd platform](/images/Users-table.png) + + +#### User editor + +Clicking on a user in the platform opens the **user editor** modal. It lets you view and manage individual user data like sign-in methods, activity history, profile fields, sessions, and more. + + +![The user editor provides details for each user](/images/rownd-user-editor.png) + + +In the user editor, you'll find: + +- **USER ID**: At the top, you'll find the user’s **Rownd ID** used to identify this unique user in your app. + +- The ability to **delete or disable** the user account from the bottom of the modal. + +- **Sign-in information**: This section shows how the user has signed in. You might see a phone number, email address, Apple ID, Google ID, anonymous ID, or wallet address—depending on what’s been used. + +- **User metadata**: Displays activity-related info for the user: when they were last active, which method they used to sign in last, when their profile was created, and when they last signed in. You can also view the full user JSON if needed. + +- **Profile data**: Shows additional data collected for the user, such as their name, age, address, job role, nickname, username, and any custom claims. If the user has a NEAR wallet, you’ll see that info too. Only fields with values will appear. + +- **Sessions & sub-brands**: Here, you can sign the user out of all active sessions. If you're using sub-brands, this section also lets you add or remove the user from sub-brands and see when they were last active in each. + +- **Email logs**: If the user has tried to sign in with email, this tab will show a list of sent email events, including recipient address, delivery status, and timestamp. It's helpful for checking deliverability and open rates. + +Want more from the user editor? If there’s something you’d like to see added to the user editor, let us know by [contacting us](mailto:support@rownd.io) or reaching out through the in-app chat. + diff --git a/rownd-docusaurus/docs/configuration/user-accounts/progressive-profiles.mdx b/rownd-docusaurus/docs/configuration/user-accounts/progressive-profiles.mdx new file mode 100644 index 0000000..0499627 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/user-accounts/progressive-profiles.mdx @@ -0,0 +1,59 @@ +--- +title: "Progressive profiles" +--- + +Progressive profiles gradually capture new or returning users as they advance through your app experience. Instead of immediately requesting an email, Rownd's progressive profiles allow you to seamlessly transition simple visitors into verified users through thoughtful prompts. + +By enabling guest users and associated automations, you can allow users to explore your product until they are ready to complete the full sign-up process without losing any of their app progress. + +#### Progressive profile milestones + +As users progress through your product's expereince, the goal is for them to eventually become a verified user. Below are the various levels of user interaction with your app and what each means. + +- **Visitor**. A visitor is simply a user that has just arrived. They have no Rownd ID or captured session at this time. + +- **Guest / Anonymous user**. When a visitor takes an action or spends a certain amount of time in your product (this is customizable) they are considered a Guest (or anonymous user). At this point the user has a Rownd ID associated with their browser or app session. + + The benefit of guest users is that their progress will be saved as long as they are accessing your app from the same device or session when they return; think about it like a saved cart on an ecommerce site. The **risk** of guest users is the potential of losing progress if they return on a difference device or browser or after a significant amount of time. + + Using Passkeys, it is possible to preserve a guest's anonymity while allowing them to sign in repeatedly or from other devices. + + You can enable guest users as a sign-in method from the sign-in methods page. + + We recommend prompting guest users to add a sign-in method as quickly as makes sense for your use case in order to prevent them from losing any account data. You can do this by assigning automated prompts at specific moments in your app. + +- **Unverified user**. Unverified users have provided a piece of verifiable information but have not yet verified it. For example, a user has provided an email address in your app, but has not claimed or verified as their own yet. At this point the user no longer runs the risk of losing account data. If they are signed out or access your app on another device, they can sign in simply by verifying their email address via the normal sign-in process. + + To enable Unverified users, navigate to the **Sign-in methods** tab and scroll down to **Sign in preferences.** Here, you can enable unverified users via the toggle. After enabling, new users that provide an email address can sign in without verifying their information on their first visit. On return visits, they will be asked to verify their account. + +
+ +
+ +- **Verified user**. A verified user has verified their account by either verifying their email or phone number, signing in with Google or Apple, or connecting a passkey to a session. Verified users are now fully authenticated and should be able to access their account information after being signed out. + + +#### Automations for capturing users at the right moment + +The following automations are available to help you capture users at the right moment in your app experience: + +1. Sign in prompt +2. Passkey prompt (coming soon!) +3. Google one tap prompt (coming soon!) +2. Capture user (coming soon!) +3. Prompt for additional information (coming soon!) + + +#### Deleting users + +According to Rownd's pricing model, you are billed based on the number of active users on your app, specifically those with associated Rownd IDs. In the case of users who remain as "Guest" or "anonymous" without any further progression, you have the option to configure your app to automatically delete their accounts after a specified period of time. diff --git a/rownd-docusaurus/docs/configuration/user-accounts/user-profiles.mdx b/rownd-docusaurus/docs/configuration/user-accounts/user-profiles.mdx new file mode 100644 index 0000000..6597f19 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/user-accounts/user-profiles.mdx @@ -0,0 +1,140 @@ +--- +title: "User Profiles" +description: "Understand the anatomy of a Rownd user profile, including user data, attributes, and metadata." +--- + +## Anatomy of a Rownd User Profile + +A Rownd user profile is a comprehensive collection of user data, attributes, and metadata that allows you to manage and understand your users effectively. This document provides an overview of the key components of a Rownd user profile. + +![Understanding the user profile](/images/user-JSON-visual.svg) + +### User data + +User data includes fields matching your app's profile data schema. This typically includes fields like: + +- **User ID**: A unique identifier for the user. +- **Email**: The user's email address. +- **Phone Number**: The user's phone number. +- **Name**: The user's full name. + +Rownd facilitates a strongly-defined user profile schema to ensure consistency and compatibility across your app. You can add as many custom fields as needed to capture additional user information. Each field specifies a data type, such as string, number, boolean, array, object, document, image, and so on. + +By default, a user can update any of their profile data (other than their user ID) through Rownd's provided UI components or APIs. You can change a field's visibility or editability settings to restrict user access to specific data. + + +Rownd profiles can store file objects like images and documnets so that you don't need additional systems for user avatars and other small artifacts. + + +### Attributes + +Attributes are custom data points that you can define and attach to a user profile. These are technically visible to the user, but they are only editable with your application credentials. Rownd's pre-built UI components won't display this data to the user, but savvy users could still view by looking at API responses in their browser (for example). + +Attribute names follow the format `namespace:key` and store an array of string values like `["value1", "value2"]`. + +You can store any attribute you want; however, note the following namespaces are reserved by Rownd, so you won't be able to create custom attributes in these namespaces. See the section on pre-defined attributes below for a list of writable reserved attributes. +- `rownd:` +- `system:` + +#### Pre-defined attributes +The following table lists all of the pre-defined attributes that Rownd uses. You can modify these attributes through Rownd's REST API or through the Rownd Platform. Invalid values within these attributes are typically ignored. + +| Attribute Name | Description | Example value | +| -------------- | ----------- | ------------- | +| `rownd:app_variants` | A list of sub-brands the user has interacted with. | `["id1234", "id5678"]` | + +#### Custom Attributes +You might decide to include your own custom attributes within a user's profile. Here are some common use cases: + +- **Custom fields**: Any additional information you want to store about the user, such as preferences, subscription status, or loyalty points. +- **Tags**: Labels that help categorize and segment users for targeted actions or communications. + +Examples: +```json +{ + "attributes": { + "myapp:loyalty_points": ["100"], + "myapp:tags": ["premium", "vip"] + } +} +``` + +### Metadata + +Metadata provides additional context about the user's interactions and status within your application. This includes: + +- **Sign-in Methods**: Information about how the user signed in (e.g., email, social login). +- **Last Sign-in Time**: The last time the user signed into your application. +- **Sub-brands**: A map of sub-brands the user has interacted with, including the sign-in method used and the last sign-in time for each sub-brand. + +Most metadata is read-only and is managed by Rownd on your behalf. You can access this information through the Rownd API or the Rownd Platform. + +### Example user profile structure + +Here is an example structure of a Rownd user profile. The `data` attribute will differ based on your app's profile schema. + +```json +{ + "data": { + "user_id": "user_a3vc29gjsaf0h", + "email": "juliet@example.com", + "phone_number": "+1234567890", + "first_name": "Juliet", + "last_name": "Rose", + "profile_picture": "https://storage.rownd.io/profile.jpg", + }, + "attributes": { + "rownd:app_variants": ["id1234", "id5678"], + "myapp:loyalty_points": ["100"], + }, + "groups": [{ + "group": { + "id": "group_dvbfjkxkvetrr0d45oa7xaoo", + "name": "My app's group", + "member_count": 0, + "app_id": "290167281732813315", + "admission_policy": "invite_only", + "created_at": "2024-07-09T15:35:31.553Z", + "updated_at": "2024-07-09T15:35:31.524Z", + }, + "member": { + "user_id": "71f6ceeb-ee0a-4437-9b44-e6229defbab8", + "roles": [ + "admin", + "owner" + ], + "id": "member_n73ophaa4ksb5dab5bnj4kfv", + "state": "active", + "invited_by": "user_1234", + "added_by": "user_1234", + "group_id": "group_dvbfjkxkvetrr0d45oa7xaoo" + } + }], + "metadata": { + "modified": "2025-01-27T16:44:05.191Z", + "first_sign_in": "2023-09-01T15:41:05.725Z", + "first_sign_in_method": "email", + "last_sign_in": "2025-01-27T16:44:05.160Z", + "last_sign_in_method": "email", + "last_active": "2025-01-27T16:44:05.160Z", + "last_token_refresh": "2023-01-25T18:09:42.248Z", + "app_variants": { + "base": { + "last_sign_in": "2025-01-27T16:44:05.160Z", + "last_sign_in_method": "email" + } + }, + "verified_date": "2024-06-05T16:43:45.510Z", + "auth_level": "verified" + }, + "state": "enabled" +} +``` + +### Managing User Profiles + +To manage user profiles, you can use the Rownd platform's user management features. This includes viewing and editing user profiles, managing sub-brands, and viewing user activity and metadata. + +For more detailed information on managing user profiles, refer to the [API reference](/api-reference/user-profiles/app/insert-update). + +By understanding the anatomy of a Rownd user profile, you can better manage your users and provide a personalized experience across your applications. diff --git a/rownd-docusaurus/docs/configuration/web3/near-examples.mdx b/rownd-docusaurus/docs/configuration/web3/near-examples.mdx new file mode 100644 index 0000000..ea43f86 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/web3/near-examples.mdx @@ -0,0 +1,66 @@ +--- +title: "Examples" +sidebarTitle: "Examples" +description: "Integrate Rownd with NEAR blockchain to provide secure wallet management and user-friendly wallet interactions for your users." +--- + + +This is a limited beta feature. Please [contact us](mailto:support@rownd.io?subject=Please%20enable%20NEAR) if you're interested in using it. + + +The Rownd NEAR integration ensures that all of your users have a NEAR account either automatically or on-dmand. + +## NEAR Examples + +Here are some basic examples of using the Rownd SDK and APIs to interact with NEAR. See the [JavaScript API Reference](/sdk-reference/web/javascript--api-reference#near) for more details + +### Trigger an implicit account creation + +If you wish to control when NEAR implicit accounts are created for your users, you can opt for the "on-demand" creation +strategy. This improves sign-up time since Rownd does not have to wait for the execution of on-chain contract calls to +complete. You will need to manually ensure that an implicit account exists for a user. + +You can execute the following SDK call to ensure an implicit account exists + + +```javascript Javascript +// accountId = "12a734486c485767d02a4747487573e69889a92618c4890328b0a18c6320898cd2" +const accountId = await rownd.near.ensureImplicitAccount(); +``` + +```sh cURL +# Invoke the 'near.ensure-implicit-account` with the user's Rownd access token +curl 'https://api.rownd.io/hub/connection_action' \ + -H 'authorization: Bearer ' \ + -H 'content-type: application/json' \ + --data-raw '{"action_type":"near.ensure-implicit-account"}' + +# Result: +# { +# "action_type": "ensure-implicit-account", +# "result": "success", +# "data": { +# "near_implicit_account_id": "3df96ef4be51736d4d76f23c801954f72e8421a7751d4e2c44bc7cee35576a70" +# } +# } +``` + + +## Prompt a user for named account creation + +This call will open a dialog prompting the user to enter a name prior to creating the NEAR account. This name will end +with `.rownd.near` by default. For instance, if a user specifies `my-account-1`, the full account name will be +`my-account-1.rownd.near`. Work with the Rownd support team if you would like to change this account name suffix to +another value. + +```javascript Javascript +rownd.near.createNamedAccount(); +``` + +## Prompt a user to connect an account + +This call will open a dialog prompting the user to connect a NEAR account. They will be presented with a list of supported wallet providers. Clicking on one of the providers will initiate a NEAR wallet sign-in, after which the NEAR account and wallet ID will be added to the Rownd user's profile data. + +```javascript Javascript +rownd.near.connectAccount(); +``` diff --git a/rownd-docusaurus/docs/configuration/web3/near-overview.mdx b/rownd-docusaurus/docs/configuration/web3/near-overview.mdx new file mode 100644 index 0000000..1c83c92 --- /dev/null +++ b/rownd-docusaurus/docs/configuration/web3/near-overview.mdx @@ -0,0 +1,152 @@ +--- +title: "Rownd Integration with NEAR" +sidebarTitle: "Overview for NEAR integration" +description: "Integrate Rownd with NEAR blockchain to provide secure wallet management and user-friendly wallet interactions for your users." +--- + + +This is a limited feature. Please [contact us](mailto:support@rownd.io?subject=Please%20enable%20NEAR) if you're interested in using it. + + +The NEAR Protocol is a scalable and user-friendly blockchain platform designed to power the next generation of decentralized applications. With its focus on simplifying the developer and user experience, NEAR is poised to drive mass-adoption of web3 technologies. + +Rownd's integration with NEAR addresses one of the most significant barriers to entry for new web3 users - the onboarding process. By automating wallet generation, securely storing private keys, and enabling seamless wallet management through each person's Rownd profile, users can easily interact with NEAR-based applications. This streamlined approach accelerates user onboarding, reduces friction, and fosters a more inclusive web3 ecosystem, empowering a wider audience to participate in the decentralized revolution. + +The integration offers the following features: + +- **Automatic wallet creation**
+ When the integration is configured, Rownd will automatically create a NEAR wallet for each user. This eliminates the need for users to manually create a wallet, streamlining the onboarding process and making it more user-friendly. + + + + + + + + + + + + + + +- **On-Demand wallet creation**
+ The integration can be configured so that a NEAR wallet is not created automatically upon user sign-in. In this + configuration, you can manually trigger the creation of the NEAR wallet at any point. See our [examples page](/configuration/web3/near-examples). + + + + + + + + + + + + + + +- **Secure private key storage**
+ Rownd securely stores the private key associated with each user's NEAR wallet using double encryption. This ensures that the private key remains safe from unauthorized access, providing a high level of security for users' assets. + +- **User wallet access**
+ Users can view their NEAR wallet balance and transaction history through the Rownd profile. This provides a convenient way for users to keep track of their wallet without needing to use a separate interface. + + + + + + + + + + + + + + +- **Named wallet creation**
+ With Rownd, users have the option to create a named wallet for their NEAR account. This makes it easy for users to remember their wallet addresses and share them with others for transactions. + + + + + + + + + + + + + + +- **Easy wallet attachment**
+ + Users can easily attach a NEAR wallet to their Rownd account, making it simple to manage their blockchain assets alongside their other authentication methods. + + + + + + + + + + + + + + +## Configuring NEAR + + +This is a limited feature. Please [contact us](mailto:support@rownd.io?subject=Please%20enable%20NEAR) if you're interested in using it. + + +To set up the Rownd NEAR integration, follow these steps: + +1. Create a Rownd NEAR integration in the Rownd platform. + + ![Create NEAR integration](/images/integration_setup1.png) + +2. Choose between "Testnet" or "Mainnet" based on your requirements. + + ![Select network ](/images/Near_setup_2.png) + +3. Enter your NEAR wallet and private key to create accounts and fund them (optional). + + ![Enter wallet details ](/images/near-setup-3.png) + +Now, your Rownd NEAR integration is set up and ready to be used by your users. + +## Data Type Updates + +After attachhing the NEAR integration to your application, Rownd will add the following fields to your application +data types. Fields marked "Encrypted" are stored encrypted in the Rownd database and only visible to the users. + + + The implicit NEAR account ID + + + The implicit private key + + + The implicit seed phrase + + + The named NEAR account ID + + + The named NEAR private key + + + The named NEAR seed phrase + + + The personal NEAR account ID + + + The personal NEAR private key + diff --git a/rownd-docusaurus/docs/magic-links/authenticated.mdx b/rownd-docusaurus/docs/magic-links/authenticated.mdx new file mode 100644 index 0000000..d3a35ef --- /dev/null +++ b/rownd-docusaurus/docs/magic-links/authenticated.mdx @@ -0,0 +1,48 @@ +--- +title: "Authenticated links" +sidebarTitle: "Authenticated links" +--- + +Authenticated magic links are a powerful tool for securely granting users access to your app or website. These links contain an embedded authentication payload that verifies the user's identity, allowing them to bypass the traditional login process. This not only enhances the user experience by providing a seamless entry point but also ensures that access is restricted to authorized users. + +When a user clicks on an authenticated magic link, they are automatically signed in and redirected to the specified destination within your app or site. This can be particularly useful for re-engaging users, onboarding new users, or directing users to specific content or features. + +To create authenticated magic links, you can use the Rownd API, which allows you to customize the link's behavior and target destination. This flexibility ensures that you can tailor the user experience to meet your specific needs while maintaining a high level of security. + +Overall, authenticated magic links offer a convenient and secure way to manage user access, making them an essential component of modern authentication strategies. + +## Creating authenticated magic links + +Authenticated magic links can only be created via the Rownd API. Since these links contain sensitive authentication information, it's essential to follow best practices for handling and distributing them securely. + +Magic links can be created via our REST API or through our SDKs. Backend SDKs can be used to create magic links for any user, while frontend SDKs can be used to create magic links for the currently authenticated user, which are useful for device-transition scenarios. + +Here's an example creating an authenticated magic link using the Rownd API. In this example, we're using an email address as the primary user identifier, setting some profile information, and specifying a redirect URL for the user. If the user exists, they will be signed in and redirected to the specified URL. If the user doesn't exist, an account will be created automatically during sign-in. + +**Request** +```bash +POST https://api.rownd.io/hub/auth/magic +Content-Type: application/json +X-Rownd-App-Key: YOUR_APP_KEY +X-Rownd-App-Secret: YOUR_APP_SECRET + +{ + "purpose": "auth", + "verification_method": "email", + "data": { + "email": "juliet@rose.com", + "first_name": "Juliet", + "last_name": "Rose" + }, + "redirect_url": "https://yourapp.com/welcome", + "expiration": "1h" +} +``` + +**Response** +```json +{ + "link": "https://rownd.link/YOUR_UNIQUE_MAGIC_LINK", + "app_user_id": "user_a1b2c3d4" +} +``` diff --git a/rownd-docusaurus/docs/magic-links/overview.mdx b/rownd-docusaurus/docs/magic-links/overview.mdx new file mode 100644 index 0000000..ca02973 --- /dev/null +++ b/rownd-docusaurus/docs/magic-links/overview.mdx @@ -0,0 +1,133 @@ +--- +title: "Overview" +sidebarTitle: "Overview" +--- + +Magic links provide a seamless authentication method for getting users into your app or website without requiring them to explicitly sign in. However, you can also use magic links for other purposes, such as re-engaging users, onboarding new users, or directing users to specific app screens. While magic links usually include an authentication payload identifying the user, they can also be used for non-authentication purposes. + +In many cases, you can replace Branch or Firebase Dynamic Links with Rownd magic links, as they provide similar functionality at no additional cost with the added benefit of integrated authentication. + +### What makes Rownd magic links unique? + +- **Integrated authentication**: Unlike standard Magic links, Rownd's Magic Links also manage user sign-in and verification, providing a streamlined login experience across devices and platforms. +- **Security first**: Each link is dynamically generated to verify user identity and restrict unauthorized access. +- **Cross-platform**: Rownd magic links are optimized for use across web, iOS, and Android, ensuring a consistent experience. +- **Unauthenticated / bulk links**: Create reusable links for bulk distribution with a customized call-to-action. Deep link into your app or website or trigger app downloads from the correct app store. This allows users to directly access the download link without requiring authentication. + +### Elevate Your Brand with Custom Domains + +One of the most powerful features of Rownd Smart Links is the ability to use your own custom domain: + +- **Enhanced Brand Trust**: Links displaying your domain instead of a third-party one significantly improve click-through rates +- **Improved Deliverability**: Email and SMS providers are less likely to flag links from established domains +- **Seamless Brand Experience**: Maintain your brand identity throughout the entire user journey +- **Professional Appearance**: Custom domains create a more polished, professional impression + +To set up custom domains for your Smart Links, visit our [Custom Domains](/configuration/custom-domains/overview) documentation. Once configured, all your Smart Links will use your branded domain, creating a cohesive experience from email or SMS all the way through to your application. + +## Creating and using smart links + +Rownd offers two powerful ways to create Smart Links, each designed for different use cases and workflow preferences: + +### Platform-Based Creation + +You can now create and manage Smart Links directly through the Rownd dashboard without writing any code. Our user-friendly interface allows you to: + +- Create reusable Smart Links for marketing campaigns, user onboarding, or app downloads +- Customize link behavior with redirects based on device type +- Add analytics tags to track link performance +- Control how your links appear when shared on social media +- Manage all your links from a central dashboard + + + +The platform approach is perfect for marketing teams, content managers, and anyone who needs to create and manage links without developer involvement. Within minutes, you can create a Smart Link that delivers a tailored experience to your users. + +For detailed instructions on creating Smart Links through the platform, see our [Platform Guide](/magic-links/platform). + +### API-Based Creation + +For developers and automated workflows, Rownd offers a powerful API for programmatically creating Smart Links. This approach enables: + +- **Dynamic link generation** based on user actions or events +- **Seamless integration** with existing marketing automation platforms +- **Bulk creation** of personalized links for email campaigns +- **Custom authentication flows** tailored to your specific business needs +- **Web hooks and callbacks** for advanced tracking and user journey orchestration + +During email or SMS sign-in, Rownd automatically generates smart links on your behalf and sends them to the user. However, you can also programmatically create smart links using the Rownd API. This allows you to customize the link's behavior, such as redirecting users to specific app screens or triggering custom actions. + +To create a magic link, see our [API documentation](/api-reference/authentication/create-magic-link). + +#### Example Request + +Here’s a basic example of how to create a Magic Link using Rownd's API: + +```bash +POST https://api.rownd.io/hub/auth/magic +Content-Type: application/json +X-Rownd-App-Key: YOUR_APP_KEY +X-Rownd-App-Secret: YOUR_APP_SECRET + +{ + "data": { + "email": "user@example.com" + }, + "redirect_url": "https://yourapp.com/welcome" +} +``` + +This request will create a Magic Link that authenticates the user when accessed and redirects them to the specified URL. + +### Example Response + +```json +{ + "link": "https://rownd.link/YOUR_UNIQUE_MAGIC_LINK" +} +``` + +You can then send this link to the user. + +### Using magic links + +If you're only using magic links on a web platform, then no additional setup is required. However, if you're using Rownd on a mobile platform like iOS or Android, you'll need to add some configuration to your app and the Rownd dashboard to get everything working properly. + +#### iOS setup + +Apple requires several changes to your app's configuration to handle magic links. They also require an Apple App Site Association (AASA) file to be properly configured; however, Rownd builds and hosts this file for you. + +To complete the required setup, follow the [iOS configuration steps](/configuration/mobile/ios). + +After setup, test your links on a physical device to confirm they redirect correctly into the app. + +#### Android setup + +Android apps require an intent filter in the `AndroidManifest.xml` file to handle magic links. Android also requires a Digital Asset Links JSON file to be properly configured; however, Rownd builds and hosts this file for you. + +To complete the required setup, follow the [Android configuration steps](/configuration/mobile/android). + +After setup, test your links on a physical device to confirm they redirect correctly into the app. + + +### App download links + +After you've configured and tested your mobile apps to handle magic links, you can also direct your mobile users to a special magic link endpoint that will automatically launch your app if it's installed or otherwise direct the user to your app listing on the appropriate app store for their device. + +To use this link, simply append `/download` to your Rownd subdomain (configured in Mobile settings). For example, if your subdomain is `myapp`, then the download link would be `https://myapp.rownd.link/download`. + +If the user is not on iOS or Android when they activate this link, it'll simply redirect them to your Rownd app's default URL + +--- + +## Additional Resources + +For more details on configuring and customizing Magic Links in Rownd, refer to the following: + +- [Rownd iOS Configuration Documentation](https://docs.rownd.io/configuration/mobile/ios) +- [Rownd Android Configuration Documentation](https://docs.rownd.io/configuration/mobile/android) +- [Create Magic Link API Reference](https://docs.rownd.io/api-reference/authentication/create-magic-link) + +--- + +This setup should help you get started with implementing Magic Links in Rownd. For any additional questions, feel free to reach out to our support team or consult the API reference. diff --git a/rownd-docusaurus/docs/magic-links/platform.mdx b/rownd-docusaurus/docs/magic-links/platform.mdx new file mode 100644 index 0000000..a6d8923 --- /dev/null +++ b/rownd-docusaurus/docs/magic-links/platform.mdx @@ -0,0 +1,126 @@ +--- +title: "Creating Smart Links in the Rownd Platform" +sidebarTitle: "Platform Guide" +--- + +Rownd's platform offers a user-friendly interface for creating and managing Smart Links without writing any code. This guide will walk you through the process of creating and customizing Smart Links directly in the Rownd dashboard. + +## Accessing Smart Links + +1. Log into your Rownd dashboard +2. Navigate to the **Smart Links** section in the left sidebar +3. This will display your existing Smart Links and provide options to create new ones + +## Creating a New Smart Link + +To create a new Smart Link: + +1. Click on **Smart Links** in the navigation menu +2. Click the "New smart link" button or equivalent option +3. You'll be presented with a multi-step form to configure your link + +### Step 1: Link Details (Required) + +![Creating a New Smart Link](/magic-links/images/new-smart-link.png) + +First, you'll need to provide basic information about your link: + +- **Link name**: A descriptive name to help you identify the purpose of this link in your dashboard +- **Link domain**: Select from your available domains (e.g., `.rownd.link`) +- **Link alias** : By default, an auto-generated string will be used. In the future, you will be able to edit it. + +#### Using Custom Domains for Your Smart Links + +When creating Smart Links, you have the option to use your own custom domain instead of the default Rownd domain. This provides several advantages: + +- **Enhanced brand recognition**: Users see your domain in the link, building trust and recognition +- **Higher click-through rates**: Custom domains typically see 20-30% higher engagement rates +- **Better deliverability**: Email platforms are less likely to filter messages containing your own domain +- **Professional appearance**: Create a cohesive brand experience throughout the user journey + +To use a custom domain with your Smart Links: + +1. First, [set up your custom domain](/configuration/custom-domains/overview) in your Rownd settings +2. When creating a new Smart Link, select your custom domain from the "Link domain" dropdown +3. All links generated will now use your branded domain + +Custom domains are especially valuable for marketing campaigns, email communications, and any customer-facing links where brand trust is essential. + +### Step 2: Link Customization (Optional) + +The customization section offers three tabs with different options: + +#### Analytics Tags + +Analytics tags help you track and filter performance data for your links. + +1. Select the **Analytics tags** tab +2. Add parameters that you want to track (e.g., `campaign`, `source`, `medium`) +3. Enter values for each parameter +4. Toggle "Include in URL" to have these parameters appear in the final URL (useful for additional analytics tracking) +5. Click "Add parameter pair" if you need more parameters + +#### Redirects + +The redirects tab allows you to control where users are sent when they click your link. + +1. Select the **Redirects** tab +2. Set your **Default redirect** URL by entering the page or URL destination +3. You can optionally check "Web only link" if you want the link to always redirect to a web page, even if the user has your app installed + +Rownd utilizes the latest in Universal link standards. If you have mobile apps that are Universal/Deep link compatible, you do not need to do anything special to use Rownd Smart Links. You can, however, edit specific app destinations by clicking on advanced. + +#### Link Preview + +Link previews control how your link appears when shared on social media and messaging platforms. + +1. Select the **Link preview** tab +2. Optionally import metadata from an existing URL by entering it in the "Import from URL" field +3. Customize the following fields: + - **Title**: The headline that appears in previews + - **Description**: A brief description of the link destination + - **Override preview image URL**: Add a custom image URL to display with your link + +![Link Preview Customization](/magic-links/images/link-preview.png) + +### Step 3: Finalize and Create + +1. Review your link settings +2. Click "Next" to proceed +3. On the review screen, click "Create Link Now" to generate your Smart Link + +## Managing Existing Smart Links + +After creating Smart Links, you can: + +- View analytics on link performance +- Edit link settings +- Delete links you no longer need +- Copy links to share them + +## Use Cases for Platform-Created Smart Links + +### User Onboarding + +Create Smart Links for email campaigns that automatically sign users in and direct them to your onboarding flow. + +### App Download Campaigns + +Generate Smart Links that detect the user's device and direct them to the appropriate app store or web experience. + +### Re-engagement Campaigns + +Create links for re-engagement emails that authenticate users and take them directly to specific content in your app. + +### Marketing Campaigns + +Use analytics tags to track the performance of different marketing channels and campaigns. + +## Best Practices + +- **Use descriptive names**: Name your links in a way that clearly indicates their purpose and campaign +- **Keep analytics consistent**: Establish a naming convention for your parameters and values +- **Test your links**: Always test your links on different devices and platforms before using them in production +- **Monitor performance**: Regularly check link analytics to optimize your campaigns (coming soon) + +Smart Links created through the platform provide the same security and cross-platform capabilities as those created via the API, but with the convenience of a visual interface. diff --git a/rownd-docusaurus/docs/magic-links/unauthenticated.mdx b/rownd-docusaurus/docs/magic-links/unauthenticated.mdx new file mode 100644 index 0000000..8ef6337 --- /dev/null +++ b/rownd-docusaurus/docs/magic-links/unauthenticated.mdx @@ -0,0 +1,34 @@ +--- +title: "Unauthenticated links" +sidebarTitle: "Unauthenticated links" +--- + +Unauthenticated magic links are a powerful tool for directing users to specific content or features within your app or website. These links can be shared publicly and do not require the user to sign in, making them ideal for marketing campaigns, promotions, or general content sharing. + +When a user clicks on an unauthenticated magic link, they are directed to the specified destination within your app or site. This can be particularly useful for driving traffic to specific pages, promoting new features, or sharing content with a wider audience. + +To create unauthenticated magic links, you can use the Rownd API, which allows you to customize the link's behavior and target destination. This flexibility ensures that you can tailor the user experience to meet your specific needs while maintaining a high level of security. + +## Creating unauthenticated magic links + +Here's an example of creating an unauthenticated magic link using the Rownd API. In this example, we're specifying a redirect URL. When someone accesses the link, they'll be directed to the specified URL without an authentication payload attached. If they've previously authenticated and still have a valid session, that session will continue. + +**Request** +```bash +POST https://api.rownd.io/hub/auth/magic +Content-Type: application/json +X-Rownd-App-Key: YOUR_APP_KEY +X-Rownd-App-Secret: YOUR_APP_SECRET + +{ + "purpose": "shorten", + "redirect_url": "https://yourapp.com/promo?code=discount" +} +``` + +**Response** +```json +{ + "link": "https://rownd.link/YOUR_UNIQUE_MAGIC_LINK" +} +``` diff --git a/rownd-docusaurus/docs/magic-links/url-parameters.mdx b/rownd-docusaurus/docs/magic-links/url-parameters.mdx new file mode 100644 index 0000000..3fe2637 --- /dev/null +++ b/rownd-docusaurus/docs/magic-links/url-parameters.mdx @@ -0,0 +1,30 @@ +--- +title: "URL parameters" +sidebarTitle: "URL parameters" +--- + +URL parameters are a powerful tool for customizing the behavior of magic links. By appending parameters to the magic link URL, you can control how the link behaves when accessed, such as redirecting users to specific app screens, triggering custom actions, or passing additional data to your app. + +After you create a magic link, any query parameters you append to the link URL will be passed through and attached to the redirect URL when the link is accessed. This is a handy tool for tracking marketing campaigns using UTM codes or passing user-specific data to your product. + +## Using URL parameters + +To use URL parameters with magic links, simply append them to the magic link URL. For example, if you have a magic link like `https://rownd.link/YOUR_UNIQUE_MAGIC_LINK`, you can add parameters like `?utm_source=facebook` to track the source of the link click. + +Here's an example of how you can use URL parameters with magic links: + +```bash +https://rownd.link/YOUR_UNIQUE_MAGIC_LINK?utm_source=facebook&utm_campaign=summer_sale +``` + +In this example, we're adding two URL parameters to the magic link: `utm_source=facebook` and `utm_campaign=summer_sale`. When a user accesses the link, these parameters will be passed through and attached to the redirect URL. + +Assuming the redirect URL is `https://yourapp.com/welcome`, the final URL that the user will be redirected to will look like this: + +```bash +https://yourapp.com/welcome?utm_source=facebook&utm_campaign=summer_sale +``` + + + For security reasons, any query parameters present in the redirect URL during magic link creation cannot be overridden by query parameters added to the magic link URL. If you have a use case where you need to override query parameters in the redirect URL, please [let us know](mailto:support@rownd.io?subject=%5BMagic%20Links%5D%20Ability%20to%20override%20query%20parameters). + diff --git a/rownd-docusaurus/docs/migration/auth0.mdx b/rownd-docusaurus/docs/migration/auth0.mdx new file mode 100644 index 0000000..ff4bb4e --- /dev/null +++ b/rownd-docusaurus/docs/migration/auth0.mdx @@ -0,0 +1,180 @@ +--- +title: "Migrating from Auth0" +sidebarTitle: "Auth0" +--- +Migrating from Auth0 to Rownd is fast and easy. In most cases, you'll probably be able to remove a lot of unnecessary code and configuration from your product in exchange for Rownd's turnkey solution. Let's get started! + +## Overview +In this guide, we'll help you plan your migration from Auth0 to Rownd so that you can think through the process and avoid any pitfalls. We'll also provide some code snippets to help you get started. + +Here's what you'll work through as part of this migration: +1. Creating a Rownd account and setting up your test and production apps. +2. Updating your code to leverage Rownd instead of Auth0. +3. Migrating your existing users to Rownd. + +We've prepared a [sample repository](https://github.com/rownd/migration-auth0#auth0-migration-to-rownd) that demonstrates the migration process from a code perspective. + +## Set up Rownd + + +5. [Create an Auth0 integration](/configuration/integrations/auth0) and attach it to your app. This will allow Rownd to migrate your existing users automatically. + +## Update back-end code +You'll need to update your backend APIs to accept Rownd-signed JWTs instead of Auth0 JWTs. Use the Rownd SDK corresponding to the framework or language of your backend API server. Check out a full list of our [backend SDKs](https://docs.rownd.io/sdk-reference/backend/overview). + +Our SDKs provide functions to validate Rownd tokens, fetch user data, and in some cases middleware that you can plug directly into your request handlers to authenticate usurs automatically. Here's an example of using the Node.js SDK's Express middleware: + +```typescript +import { createInstance } from '@rownd/node'; +const rownd = createInstance({ + app_key: 'YOUR_APP_KEY', + app_secret: 'YOUR_APP_SECRET', +}); +const { authenticate } = rownd.express; + +app.get('/api/*', authenticate({ fetchUserInfo: true })); + +app.get('/api/profile', (req, res) => { + res.send({ + profile: req.user + }); +}); +``` + +Notice the use of the `authenticate` middleware function from `rownd.express` which validates a JWT in the `Authorization` header and fetches profile data from Rownd, making it available on the request object for other request handlers. You can also build a middlware yourself or use one-off instances of `rownd.validateToken(token);` and `rownd.fetchUserInfo(token);`. + +## Update front-end code +Next, you'll need to replace Auth0 with Rownd in your frontend. The exact steps will vary depending on the frontend framework you're using and the authentication features of Auth0 that you are utilizing. We'll use React as an example to demonstrate the steps below. + +1. Install the `@rownd/react` dependency with your preferred package manager +2. Add the `RowndProvider` context provider. + +In your app's entrypoint file, add the `RowndProvider` context provider. You should already have an `Auth0Provider` somewhere in your app, which can help you find where you need to add this. + + +To keep existing users signed in during the migration, leave the existing `Auth0Provider` in place for now. Find out more about [keeping users signed in](#keep-existing-users-signed-in) during the migration. + + + + ```tsx RowndProvider + import { RowndProvider } from '@rownd/react'; + + const root = createRoot(document.getElementById('root')); + root.render( + + + + + , + ); + ``` + + +3. Replace Auth0 hook with Rownd + +Auth0 provides a React hook named `useAuth0()` that you'll need to replace with Rownd. Rownd exposes similar properties and functions through the `useRownd()` hook. It should be pretty straightforward to swap out the Auth0 hook to use Rownd's, and to adapt your code to use the Rownd properties. + + + ```typescript useRownd() hook + // const { isAuthenticated, user } = useAuth0(); + const { is_authenticated, user } = useRownd(); + if (is_authenticated) { + return user.data.email; + } + ``` + + +**Notable Differences** + +**_Enforcing authentication for protected components_** + +If you have components protected with Auth0's `withAuthenticationRequired` component, you'll need to add the some equivalent Rownd code to enforce authentication. Use the `useRownd()` hook to enforce authentication upon rendering of certain components + + +```typescript Example +const { is_initializing, is_authenticated, requestSignIn } = useRownd(); +if (!is_initializing && !is_authenticated) { + requestSignIn({ prevent_closing: true }); +} +``` + + +**_Audiences and APIs_** + +Rownd backend SDKs automatically validate the audience claim in Rownd-issued JWTs. Unlike Auth0, you do not need to explicitly set the audience and API configuration parameters in the SDK itself. You can remove any code present in your React app that configures or depends on audiences. If you want to set additional audience values, you can do so in the Rownd Platform under Application Settings. + +**_OAuth redirects_** + +The Rownd React SDK and Javascript snippet itself handle all redirects associated with authentication flows. If you have frontend code that handles callbacks or redirects from Auth0, you can safely remove these. They are no longer needed with Rownd. + +## Keep existing users signed-in +Migrating your authentication to Rownd will help convert more users as they move through your funnel; however, what about the users you already have? They'll quickly become frustrated if they get signed out as a result of the migration. + +To keep existing users signed in, you can pass their old Auth0 access token to Rownd for validation. Rownd will then issue a new token to the user so they'll be able to continue using your product without interruption. Once the new token is issued, the auth0 token can be permanently discarded. + +Here's a full example using the Rownd React SDK. We'll break down the details below: + + + ```typescript Example + const { is_initializing, is_authenticated, getAccessToken } = useRownd(); + const auth0 = useAuth0(); + useEffect(() => { + if (is_authenticated) { + return; + } + if (!is_initializing && !auth0.isLoading && auth0.isAuthenticated) { + auth0.getAccessTokenSilently().then((auth0Token) => { + getAccessToken({ token: auth0Token }) + }); + } + }, [getAccessToken, is_authenticated, is_initializing, auth0]) + ``` + + +1. In your front-end code, at the top-level component, check if the user is already signed in to Rownd. If they are, you're done! + + + ```typescript + if (is_authenticated) { + return; + } + ``` + + + +2. If they aren't, check if they're currently authenticated via Auth0. If they are, retrieve their ID token. + + + + ```typescript + if (!is_initializing && !auth0.isLoading && auth0.isAuthenticated) { + auth0.getAccessTokenSilently().then((auth0Token) => { + getAccessToken({ token: auth0Token }) + }); + } + ``` + + + +3. Pass the token to Rownd for validation. If the token is valid, Rownd will issue a new token to the user. + + + + ```typescript + getAccessToken({ token: auth0Token }) + ``` + + + +4. `is_authenticated` should now be `true` and the user can continue using your product normally. + +## Sync user profiles (optional) +Rownd supports multiple ways to sync your user data from Auth0. If you created and attached the [Auth0 integration](/configuration/integrations/auth0) to your app, Rownd will begin migrating users "just in time," meaning that as users sign in, their data will automatically be imported into Rownd (matched on email address, phone number, etc). + +However, pre-loading user data into Rownd will speed up the initial authentication handshake. You can use the Auth0 connector's "sync" option to do a bulk import of all users from your Auth0 app to Rownd. Any users that sign-in after the sync begins will be auto-migrated using the "just in time" method. + + + + diff --git a/rownd-docusaurus/docs/migration/cognito.mdx b/rownd-docusaurus/docs/migration/cognito.mdx new file mode 100644 index 0000000..4781cb4 --- /dev/null +++ b/rownd-docusaurus/docs/migration/cognito.mdx @@ -0,0 +1,171 @@ +--- +title: "Migrating from AWS Cognito" +sidebarTitle: "Cognito (AWS)" +--- + +## Overview + +Here's what you'll work through as part of this migration: +1. Creating a Rownd account and setting up your test and production apps. +2. Updating your code to leverage Rownd instead of Cognito for authentication. +3. Migrating your existing users to Rownd. + +We've prepared a [sample repository](https://github.com/rownd/migration-cognito#cognito-migration-to-rownd) that demonstrates the migration process from a code perspective. + +## Set up Rownd + + + +## Update back-end code +You'll need to update your backend APIs to accept Rownd-signed JWTs instead of AWS Cognito JWTs. + + 1. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend/overview). + 2. Locate code that uses the AWS Cognito to manage users, validate tokens, and so on. Remove this code. + +Our SDKs provide functions to validate Rownd tokens, fetch user data, and in some cases middleware that you can plug directly into your request handlers to authenticate users automatically. + +Here's an example using Express middleware in Node.js: + + +Notice the use of the `authenticate` middleware function from `rownd.express` which validates a JWT in the `Authorization` header and fetches profile data from Rownd, making it available on the request object for other request handlers. You can also build a middleware yourself or use one-off instances of `rownd.validateToken(token)` and `rownd.fetchUserInfo(token)`. + + +```typescript +import { createInstance } from '@rownd/node'; +const rownd = createInstance({ + app_key: 'YOUR_APP_KEY', + app_secret: 'YOUR_APP_SECRET', +}); +const { authenticate } = rownd.express; + +app.get('/api/*', authenticate({ fetchUserInfo: true })); + +app.get('/api/profile', (req, res) => { + res.send({ + profile: req.user + }); +}); +``` + +## Update front-end code + +1. Install the `@rownd/react` dependency with your preferred package manager +``` +npm install @rownd/react +``` + +2. Add the `` to the app's main entry. + +```typescript React .tsx +import React from 'react', +import ReactDOM from 'react-dom'; +import { RowndProvider } from '@rownd/react'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +``` + + + +3. Replace all sign up and sign in buttons to trigger the `requestSignIn` flow for new or existing users. + +```typescript +const { requestSignIn } = useRownd(); + +``` + +4. Replace ConfirmSignUp with is_authenticated API request + +```typescript +const { is_authenticated } = useRownd(); +return ( + <> + {is_authenticated && } + {!is_authenticated && } + +); +``` + + +5. Replace InitiateAuth with getAccessToken API request + +```typescript +const { getAccessToken } = useRownd(); + +let accessToken = await getAccessToken({ + waitForToken: false, +}); +``` + +6. Replace sign out buttons to send a signOut API request + +```typescript +const { signOut } = useRownd(); + +``` + +## Sync user profiles (optional) + +Export user data, then import it + +1. To do a bulk import of all users from your Cognito to Rownd see our [GitHub repo](https://github.com/rownd/csv-exporter) to export user data and transform your user data to the correct schema + +2. Then use the following script to import your users into Rownd. + + +``` +const axios = require('axios'); +let data = JSON.stringify({ + "users": [ + { + "user_id": "__default__", + "data": { + "email": "romeo@gmail.com", + "sub": "41dbf550-1031-70e1-cc01-ce0106007d33" + } + }, + { + "user_id": "__default__", + "data": { + "email": "johndoe@mailinator.com", + "sub": "518b35f0-9081-707d-5814-54cb79d27cc6" + } + }, + { + "user_id": "__default__", + "data": { + "email": "janedoe@gmail.com", + "sub": "910b8560-c071-70a3-09e3-ef0bd61a8168" + } + } + ] +}); + +let config = { + method: 'put', + maxBodyLength: Infinity, + url: 'https://api.rownd.io/applications//users/data', + headers: { + 'x-rownd-app-key': '', + 'x-rownd-app-secret': '', + 'Content-Type': 'application/json', + }, + data : data +}; + +axios.request(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); + +``` + \ No newline at end of file diff --git a/rownd-docusaurus/docs/migration/firebase.mdx b/rownd-docusaurus/docs/migration/firebase.mdx new file mode 100644 index 0000000..f8078b0 --- /dev/null +++ b/rownd-docusaurus/docs/migration/firebase.mdx @@ -0,0 +1,114 @@ +--- +title: "Migrating from Firebase Authentication" +sidebarTitle: "Firebase" +--- +Migrating from Firebase Authentication to Rownd is fast and easy. In most cases, you'll probably be able to remove a lot of unnecessary code and configuration from your product in exchange for Rownd's turnkey solution. Let's get started! + +## Overview +In this guide, we'll help you plan your migration from Firebase to Rownd so that you can think through the process and avoid any pitfalls. We'll also provide some code snippets to help you get started. + +Here's what you'll work through as part of this migration: +1. Creating a Rownd account and setting up your test and production apps. +2. Updating your code to leverage Rownd instead of Firebase for authentication. +3. Migrating your existing users to Rownd. + +We've prepared a [sample repository](https://github.com/rownd/migration-firebase#firebase-migration-to-rownd) that demonstrates the migration process from a code perspective. + +## Set up Rownd + + +5. [Create a Firebase Authentication integration](/configuration/integrations/firebase/authentication) and attach it to your app. This will allow Rownd to migrate your existing users automatically. + +## Update back-end code + +Some Firebase apps don't have a back-end component. If that's the case for you, you can skip this section! + +In most cases, you should be able to remove all Firebase Authentication-related code from any backend servers or functions you're using. Take the following steps to migrate your back-end from Firebase Authentication to Rownd. + +1. If you're only using Firebase Authentication, uninstall Firebase SDKs from your back-end project. +2. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend/overview). +2. Locate code that uses the Firebase SDK to manage users, validate tokens, and so on. Remove this code. +3. Replace the previous Firebase code with Rownd code. See our [GitHub repo](https://github.com/rownd/migration-firebase) for an example of this code migration. + +## Update front-end code +Firebase provides a limited amount of pre-built UI, so it's likely you've created some custom UI to handle sign-in and sign-up. Rownd provides a fully customizable UI that you can use to replace your existing UI. Take the following steps to migrate your front-end from Firebase Authentication to Rownd. + +If you plan to keep existing users signed-in (and you should!), keep your Firebase SDKs installed until you've migrated all of your active users to Rownd. This usually takes a month or two depending on your users' behavior patterns. + +1. Remove existing authentication code, authentication screens, and so on. (If you're migrating a mobile app, you may want to keep the splash screen, although Rownd can help you let users into your app before they fully authenticate). +2. Install a [front-end web SDK](/sdk-reference/web/overview) or [mobile SDK](/sdk-reference/mobile/overview) for your platform or framework. +3. Add the required bits of Rownd code to authenticate users and protect your front-end. + +Here's an example where we'll update the front-end and replace Firebase authentication with Rownd. React code examples are provided for demonstration purposes. + +1. Remove all code related to Firebase. If you'd like to keep existing users signed in during migration, a `getAuth(app)` instance from Firebase will still be required. + +2. Install Rownd. +``` +npm install @rownd/react +``` + +3. Add the RowndProvider to the app's main entry. + +```typescript React .tsx +import React from 'react', +import ReactDOM from 'react-dom'; +import { RowndProvider } from '@rownd/react'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +``` + + +4. Add a sign-in trigger to all protected pages: + +```typescript React .tsx +import { useRownd } from '@rownd/react'; +export default function MyProtectedComponent(props) { + const { is_authenticated, requestSignIn, is_initializing } = useRownd(); + useEffect(() => { + if (!is_authenticated && !is_initializing) { + requestSignIn() + } + }, [is_authenticated, is_initializing, requestSignIn]); +} +``` + + +## Keep existing users signed-in +Migrating your authentication to Rownd will help convert more users as they move through your funnel; however, what about the users you already have? They'll quickly become frustrated if they get signed out as a result of the migration. + +To keep existing users signed in, you can pass their old access token to Rownd for validation. Rownd will then issue a new token to the user, so they'll be able to continue using your product without interruption. Once the new token is issued, the old provider's token can be permanently discarded. + +1. In your front-end code, check if the user is already signed in to Rownd (e.g., `rownd.isAuthenticated`). If they are, you're done! +2. If they aren't, check if they're currently authenticated via Firebase. If they are, retrieve their ID token. + ```typescript + import { getAuth } from "firebase/auth"; + const firebaseConfig = { ... }; + const app = initializeApp(firebaseConfig); + const auth = getAuth(app); + + if (auth.currentUser) { + const token = await auth.currentUser.getIdToken(); + } + ``` +3. Pass the token to Rownd for validation. If the token is valid, Rownd will issue a new token to the user. + ```typescript + const token = await rownd.getAccessToken(token); + ``` +4. `rownd.isAuthenticated` should now be `true` and the user can continue using your product normally. + +## Sync user profiles (optional) +Rownd supports multiple ways to sync your user data from Firebase. Once the Firebase integration is created and attached to your app, Rownd will begin migrating users "just in time," meaning that as users sign in, their data will automatically be imported into Rownd (matched on email address, phone number, etc). + +However, pre-loading user data into Rownd will speed up the initial authentication handshake. You can use the Firebase connector's "sync" option to do a bulk import of all users from your Firebase app to Rownd. Any users that sign-in after the sync begins will be auto-migrated using the "just in time" method. + + + + diff --git a/rownd-docusaurus/docs/migration/overview.mdx b/rownd-docusaurus/docs/migration/overview.mdx new file mode 100644 index 0000000..358cfe9 --- /dev/null +++ b/rownd-docusaurus/docs/migration/overview.mdx @@ -0,0 +1,80 @@ +--- +title: "Overview" +sidebarTitle: "Overview" +description: "Flee static sign-in and move to Rownd with ease" +--- +Whether you use Auth0, Stytch, Cognito, Firebase, or you built a custom solution, moving to something new can seem like an overwhelming task. However, with Rownd, it's not hard or overwhelming. We've made it super easy for you to migrate. + +A few things to consider when leaving your current auth provider: + +1. The easiest part is moving the data. User profiles, emails, phone numbers, even Google IDs can be imported into Rownd. In many cases, this can even happen automatically. +2. Consider keeping users signed-in through the migration--your users will love you for it. This means you'll temporarily run two auth providers in parallel. + +Let's dig in. + +## Set up Rownd +The first step is to confgiure Rownd in your dev enviornment. We have a plethora of SDKs and code snippets to make this straight-forward. + +### Considerations when setting up Rownd +1. **No sign-in page:** Rownd is different. You won't need a sign-in page. Simply trigger the Rownd sign-in flow from existing buttons or trigger sign-in dynamically. It's your choice. + +2. **No difficult coding:** Rownd provides all of the authentication UI out of the box, so you won't need to build anything yourself. Applying branding, authenticaton options, and more can be configured dynamically through the Rownd platform. + +3. **Move auth where you need it:** Although some customers simply replace their existing sign-in flows with Rownd, we recommend moving authentication deeper into your offering. Letting your customers experience some of your product prior to requesting registration is a great way to boost your conversion rate. + +## Keeping users signed-in + +Rownd provides a [token validator](/configuration/integrations/token-validator) integration that can take an existing authentication token and validate it against another provider's API or JWK endpoint. This allows users that are already signed-in to stay signed-in while Rownd issues them a new token. + +### Considerations for token validaiton +1. The API or JWK endpoint needs to be public so Rownd can validate the token. +2. Each auth provider has their own methods for validating tokens. Reach out to support@rownd.io and we'll help you configure the provider to validate tokens to keep your users signed-in. + +## Setting up Google and/or Apple sign-in +If you already had [Google](/configuration/authentication-methods/google) or [Apple](/configuration/authentication-methods/apple) sign-in options, you can set them up quickly in Rownd as well. + +### Considerations for setting up Google and/or Apple sign-in +1. Use the same Google Client ID that you used to set up the authentication prior to migration. This ensures the Google ID remains the same. If that's not possible for some reason, Rownd can still automatically users based on their Google account's email address. +2. Use the same Apple App ID for both. + +## Migrating data +Migrating existing user profiles is the easiest part. If you're migrating from another auth provider, Rownd can automatically migrate your users for you. See our provider-specific migration guides for more information. + +If you're migrating from an auth provider that Rownd doesn't support natively, or if you're coming from your own auth solution, [reach out to us](mailto:migration@rownd.io?subject=Migrating%20to%20Rownd%20from%20another%20provider) a few days before deploying to production. We'll provide hands-on assistance to ensure your migration is smooth. + +### Considerations for migrating data +1. Consider what data you want to transfer to Rownd. Most sign-in methods should be migrated. Rownd can also manage other profile information (names, addresses, etc). +2. You may choose to migrate data from two or more sources. For example, you may move profile data from Auth0 and personal information (PII) from your own database. Let us know! + +## Start a migration +Choose your migration path below to get started! + + + } + icon-type="duotone" + href="/migration/auth0"> + Reduce expenses and improve your user experience + + + Say goodbye to AWS's frustrating auth tools + + } + href="/migration/firebase" > + Use Rownd with your existing Firebase project + + + Another auth provider or your own custom solution + + + diff --git a/rownd-docusaurus/docs/payments/app-setup.mdx b/rownd-docusaurus/docs/payments/app-setup.mdx new file mode 100644 index 0000000..c1f6e18 --- /dev/null +++ b/rownd-docusaurus/docs/payments/app-setup.mdx @@ -0,0 +1,726 @@ +--- +title: "Rownd Subscriptions Integration Guide" +sidebarTitle: "Integration Guide" +--- + +This guide provides a complete overview of integrating Rownd Subscriptions into your React application. + +## Table of Contents +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [API Methods](#api-methods) +- [Response Structures](#response-structures) +- [Implementation Examples](#implementation-examples) +- [Best Practices](#best-practices) +- [Quick-Start Implementation Prompt](#quick-start-implementation-prompt) +- [Understanding the API Methods and IDs](#understanding-the-api-methods-and-ids) + - [Finding and Using Subscription IDs](#finding-and-using-subscription-ids) + - [API Methods in Detail](#api-methods-in-detail) + - [Common Patterns and Gotchas](#common-patterns-and-gotchas) + + +## Overview + +Rownd Subscriptions provides a simple API to manage subscription plans and user subscriptions in your application. The API is accessible through the global `window.rownd` object. + +## Prerequisites + +1. Rownd SDK must be installed and configured in your application +2. User must be authenticated to access subscription features +3. Subscription plans must be configured in your Rownd dashboard + +## API Methods + +### 1. Get Available Subscription Plans + +```javascript +await window.rownd.subscriptions.available() +``` + +**Description:** Fetches all available subscription plans for the current application. + +**Returns:** Promise that resolves to an object containing available subscription plans. + +### 2. Subscribe to a Plan + +```javascript +await window.rownd.subscriptions.subscribe(subscriptionId, planId) +``` + +**Parameters:** +- `subscriptionId` (string): The subscription ID from the available plans response +- `planId` (string): The specific plan/price ID to subscribe to (format: `prod_XXX__price_YYY`) + +**Returns:** Promise that resolves when subscription is successful (status 200). + +### 3. List User's Subscriptions + +```javascript +await window.rownd.subscriptions.list() +``` + +**Description:** Fetches all active subscriptions for the authenticated user. + +**Returns:** Promise that resolves to an object containing the user's subscriptions. + +## Response Structures + +### Available Plans Response + +```javascript +{ + results: [ + { + created_at: "2025-06-03T01:01:15.708Z", + id: "sub_r7i3j3hf7nliv0somxl99d08", // This is the subscriptionId + presentation: { + options: [ + { + active: true, + billing_scheme: "per_unit", + created: 1748912473, + currency: "usd", + description: "Starter plan", + hub_visible: true, + id: "prod_SQaOuPZleHnMXY__price_1RVjE5FKMLRRRtblfOWelt8y", // This is the planId + livemode: true, + name: "Starter", + nickname: "Free trial", + object: "price", + product: { + id: 'prod_SQaOuPZleHnMXY', + object: 'product', + active: true, + // ... additional product details + }, + recurring: { + interval: 'month', + interval_count: 1, + trial_period_days: null, + usage_type: 'licensed' + }, + unit_amount: 0, // Price in cents + unit_amount_decimal: "0" + }, + { + // ... additional plan options + } + ] + }, + provider: "stripe", + provider_connection_id: "cmbftbsvv01cffg3rg3qwhsdl", + updated_at: "2025-06-03T01:26:37.563Z" + } + ], + total_results: 1 +} +``` + +### User Subscriptions Response + +```javascript +{ + results: [ + { + app_subscription_id: "sub_r7i3j3hf7nliv0somxl99d08", + billing_cycle_anchor: 1749155826, + cancel_at_period_end: false, + created: 1749155826, + created_at: "2025-06-05T20:37:06.000Z", + currency: "usd", + customer: "cus_SRdicauykfzG8Z", + id: "stripe|sub_1RWkX8FKMLRRRtbl01wU54sW", + livemode: true, + plan: { + id: 'price_1RVjE5FKMLRRRtblfOWelt8y', + object: 'plan', + active: true, + amount: 0, + amount_decimal: '0', + // ... additional plan details + }, + status: "active", // Can be: active, trialing, canceled, etc. + updated_at: "2025-06-05T20:37:13.966Z" + } + ], + total_results: 1 +} +``` + +## Implementation Examples + +### Example 1: Fetching and Displaying Available Plans + +```javascript +import { useState, useEffect } from 'react' + +function SubscriptionPlans() { + const [plans, setPlans] = useState([]) + const [loading, setLoading] = useState(false) + + const fetchAvailablePlans = async () => { + setLoading(true) + try { + const response = await window.rownd.subscriptions.available() + if (response.results && response.results.length > 0) { + // Extract plans from the first result's presentation options + setPlans(response.results[0].presentation.options || []) + } + } catch (error) { + console.error('Error fetching plans:', error) + } finally { + setLoading(false) + } + } + + useEffect(() => { + fetchAvailablePlans() + }, []) + + const formatPrice = (amount, currency) => { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: currency.toUpperCase() + }).format(amount / 100) // Convert cents to dollars + } + + return ( +
+ {loading ? ( +

Loading plans...

+ ) : ( +
+ {plans.map((plan) => ( +
+

{plan.name}

+

{plan.description}

+

{formatPrice(plan.unit_amount, plan.currency)}/{plan.recurring.interval}

+ {plan.recurring.trial_period_days && ( +

{plan.recurring.trial_period_days} day free trial

+ )} +
+ ))} +
+ )} +
+ ) +} +``` + +### Example 2: Subscribing to a Plan + +```javascript +const handleSubscribe = async (subscriptionId, planId) => { + try { + const response = await window.rownd.subscriptions.subscribe(subscriptionId, planId) + + if (response.status === 200 || response.ok) { + console.log('Successfully subscribed!') + // Handle success (e.g., show success message, refresh subscriptions) + } + } catch (error) { + console.error('Subscription failed:', error) + // Handle error (e.g., show error message) + } +} + +// Usage example: +// subscriptionId comes from available() response: response.results[0].id +// planId comes from the specific plan: plan.id +handleSubscribe("sub_r7i3j3hf7nliv0somxl99d08", "prod_SQaOuPZleHnMXY__price_1RVjE5FKMLRRRtblfOWelt8y") +``` + +### Example 3: Displaying User's Subscriptions + +```javascript +import { useState, useEffect } from 'react' + +function MySubscriptions() { + const [subscriptions, setSubscriptions] = useState([]) + const [loading, setLoading] = useState(false) + + const fetchMySubscriptions = async () => { + setLoading(true) + try { + const response = await window.rownd.subscriptions.list() + if (response.results) { + setSubscriptions(response.results) + } + } catch (error) { + console.error('Error fetching subscriptions:', error) + } finally { + setLoading(false) + } + } + + useEffect(() => { + fetchMySubscriptions() + }, []) + + const formatDate = (dateString) => { + return new Date(dateString).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }) + } + + return ( +
+ {loading ? ( +

Loading subscriptions...

+ ) : subscriptions.length === 0 ? ( +

No active subscriptions

+ ) : ( +
+ {subscriptions.map((sub) => ( +
+

{sub.plan?.name || 'Subscription'}

+

Status: {sub.status}

+

Started: {formatDate(sub.created_at)}

+

Next billing: {formatDate(new Date(sub.billing_cycle_anchor * 1000))}

+
+ ))} +
+ )} +
+ ) +} +``` + +## Best Practices + +### 1. Error Handling +Always wrap API calls in try-catch blocks to handle potential errors gracefully: + +```javascript +try { + const response = await window.rownd.subscriptions.available() + // Handle success +} catch (error) { + console.error('Error:', error) + // Show user-friendly error message +} +``` + +### 2. Loading States +Provide visual feedback during API calls: + +```javascript +const [loading, setLoading] = useState(false) + +const fetchData = async () => { + setLoading(true) + try { + // API call + } finally { + setLoading(false) + } +} +``` + +### 3. Authentication Check +Ensure user is authenticated before showing subscription features: + +```javascript +import { useRownd } from '@rownd/react' + +function SubscriptionFeature() { + const { is_authenticated } = useRownd() + + if (!is_authenticated) { + return

Please sign in to view subscriptions

+ } + + // Show subscription content +} +``` + +### 4. Price Formatting +Always format prices for display (Stripe stores amounts in cents): + +```javascript +const formatPrice = (amount, currency) => { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: currency.toUpperCase() + }).format(amount / 100) +} +``` + +### 5. Date Formatting +Convert Unix timestamps to readable dates: + +```javascript +const formatDate = (timestamp) => { + return new Date(timestamp * 1000).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }) +} +``` + +## Common Use Cases + +### 1. Subscription Selection Modal +Create a modal that displays available plans and allows users to subscribe. + +### 2. Subscription Management Page +Show users their current subscriptions with details like billing dates and status. + +### 3. Upgrade/Downgrade Flow +Allow users to change their subscription plan by showing available options. + +### 4. Trial Period Handling +Display trial information and countdown for plans with trial periods. + +### 5. Celebration Modal for Successful Subscriptions +Create a delightful upgrade experience to celebrate when users successfully subscribe to a plan. + +#### Implementation Example: + +```javascript +import { useState } from 'react' + +function SubscriptionWithCelebration() { + const [showSuccess, setShowSuccess] = useState(false) + const [fadeOut, setFadeOut] = useState(false) + const [planName, setPlanName] = useState('') + + const handleSubscribe = async (subscriptionId, planId, planName) => { + try { + const response = await window.rownd.subscriptions.subscribe(subscriptionId, planId) + + if (response) { + // Show celebration + setPlanName(planName) + setShowSuccess(true) + setFadeOut(false) + + // Start fade out after 4 seconds + setTimeout(() => setFadeOut(true), 4000) + + // Remove celebration after fade completes + setTimeout(() => { + setShowSuccess(false) + setFadeOut(false) + }, 4800) + } + } catch (error) { + console.error('Subscription failed:', error) + } + } + + if (showSuccess) { + return ( +
+
+

Congrats on upgrading to {planName}!

+
+ {/* Your celebration animation here */} +
+
+
+ ) + } + + // ... rest of your component +} +``` + +#### CSS for Celebration Animation: + +```css +.celebration-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(102, 51, 153, 0.8); /* Purple overlay */ + display: flex; + align-items: center; + justify-content: center; + z-index: 2000; + animation: fadeIn 0.8s cubic-bezier(0.4, 0, 0.2, 1); +} + +.celebration-overlay.fade-out { + animation: fadeOut 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards; +} + +.celebration-content h1 { + color: white; + font-size: 48px; + font-weight: 700; + animation: slideDownFadeIn 1s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +/* Circular wipe animation example */ +.celebration-animation { + width: 200px; + height: 200px; + border-radius: 50%; + position: relative; + overflow: hidden; + animation: scaleInRotate 1s cubic-bezier(0.34, 1.56, 0.64, 1) 0.3s both; +} + +.celebration-animation::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: conic-gradient( + from 0deg, + transparent 0deg, + rgba(255, 255, 255, 0.4) 30deg, + transparent 90deg + ); + animation: circularWipe 2.5s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes fadeOut { + from { opacity: 1; } + to { opacity: 0; } +} + +@keyframes slideDownFadeIn { + from { + opacity: 0; + transform: translateY(-50px) scale(0.9); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@keyframes scaleInRotate { + from { + opacity: 0; + transform: scale(0.3) rotate(-180deg); + } + to { + opacity: 1; + transform: scale(1) rotate(0deg); + } +} + +@keyframes circularWipe { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} +``` + +#### Best Practices for Celebration Modals: + +1. **Timing**: Show celebration for 4-5 seconds total +2. **Smooth Transitions**: Use cubic-bezier easing for natural motion +3. **Fade Out**: Always fade out before removing to avoid jarring transitions +4. **Accessibility**: Ensure celebration doesn't interfere with screen readers +5. **Performance**: Use CSS animations instead of JavaScript for better performance +6. **Customization**: Match celebration colors to your brand + +## Troubleshooting + +### Issue: "Cannot read properties of undefined" +**Solution:** Ensure `window.rownd` is available before making API calls. The Rownd SDK must be fully initialized. + +### Issue: Subscription fails silently +**Solution:** Check the response object and console for error details. Ensure the user has valid payment methods if required. + +### Issue: Empty subscription list +**Solution:** Verify that subscription plans are properly configured in your Rownd dashboard and that the user is authenticated. + +## Additional Notes + +- All subscription amounts are in cents (multiply by 100 when saving, divide by 100 when displaying) +- The `subscriptionId` is different from the `planId` - use the correct one for each API call +- Subscription status can be: active, trialing, canceled, past_due, etc. +- Always handle the case where a user has no active subscriptions + +## Quick-Start Implementation Prompt + +> **Copy and paste this prompt into Cursor to implement Rownd Subscriptions in your app:** + +```prompt +I need to implement Rownd Subscriptions in my React application. Please help me create the following components and functionality: + +1. Create a SubscriptionPlans component that: + - Uses the Rownd SDK to fetch available plans + - Displays plans in a grid with pricing, descriptions, and trial periods + - Handles loading states and errors + - Uses proper price formatting (cents to dollars) + +2. Create a SubscribeButton component that: + - Takes subscriptionId and planId as props + - Handles the subscription process using window.rownd.subscriptions.subscribe() + - Shows loading state during subscription + - Displays success/error messages + - Includes a celebration animation on successful subscription + +3. Create a MySubscriptions component that: + - Lists the user's active subscriptions + - Shows subscription status, start date, and next billing date + - Handles the case of no active subscriptions + - Includes proper date formatting + +4. Add proper error handling and loading states throughout + - Use try/catch blocks for all API calls + - Show loading spinners during API calls + - Display user-friendly error messages + +5. Implement authentication checks: + - Use useRownd() hook to check authentication status + - Show appropriate messages for unauthenticated users + +Please use the following API methods: +- window.rownd.subscriptions.available() +- window.rownd.subscriptions.subscribe(subscriptionId, planId) +- window.rownd.subscriptions.list() + +Include proper TypeScript types, error handling, and loading states. Follow the best practices from the Rownd documentation for subscription management. +``` + +> **Note:** This prompt is designed to work with Cursor's AI capabilities to generate a complete implementation based on the Rownd Subscriptions documentation. The generated code will include proper error handling, loading states, and TypeScript types. + +## Understanding the API Methods and IDs + +### Finding and Using Subscription IDs + +When working with Rownd Subscriptions, you'll need to understand two important IDs: + +1. **subscriptionId**: This is the ID of the subscription configuration in your Rownd dashboard. You can find this by: + - Calling `window.rownd.subscriptions.available()` + - Looking at the `id` field in the response (e.g., `"sub_r7i3j3hf7nliv0somxl99d08"`) + - This ID represents the subscription configuration, not a user's subscription + +2. **planId**: This is the specific plan/price ID within a subscription. You can find this by: + - Looking at the `presentation.options[].id` field in the available plans response + - Format is typically `prod_XXX__price_YYY` + - This ID represents the specific plan a user can subscribe to + +### API Methods in Detail + +#### 1. Fetching Available Plans +```javascript +const response = await window.rownd.subscriptions.available() +``` +- Returns all subscription plans configured in your Rownd dashboard +- Response structure: + ```javascript + { + results: [{ + id: "sub_r7i3j3hf7nliv0somxl99d08", // This is your subscriptionId + presentation: { + options: [{ + id: "prod_XXX__price_YYY", // This is your planId + name: "Starter", + description: "Starter plan", + unit_amount: 0, // Price in cents + recurring: { + interval: 'month', + trial_period_days: null + } + }] + } + }] + } + ``` + +#### 2. Subscribing to a Plan +```javascript +await window.rownd.subscriptions.subscribe(subscriptionId, planId) +``` +- Parameters: + - `subscriptionId`: From the available() response (e.g., `"sub_r7i3j3hf7nliv0somxl99d08"`) + - `planId`: From the plan options (e.g., `"prod_XXX__price_YYY"`) +- Returns: Promise that resolves on successful subscription +- Status codes: + - 200: Success + - 400: Invalid parameters + - 401: Unauthenticated + - 402: Payment required + - 403: Forbidden + +#### 3. Listing User's Subscriptions +```javascript +const response = await window.rownd.subscriptions.list() +``` +- Returns all active subscriptions for the authenticated user +- Response structure: + ```javascript + { + results: [{ + id: "stripe|sub_1RWkX8FKMLRRRtbl01wU54sW", + status: "active", // active, trialing, canceled, etc. + created_at: "2025-06-05T20:37:06.000Z", + billing_cycle_anchor: 1749155826, + plan: { + id: 'price_1RVjE5FKMLRRRtblfOWelt8y', + amount: 0, + // ... additional plan details + } + }] + } + ``` + +### Common Patterns and Gotchas + +1. **Finding the Right IDs**: + ```javascript + // Example of extracting IDs from available plans + const availablePlans = await window.rownd.subscriptions.available() + const subscriptionId = availablePlans.results[0].id + const planId = availablePlans.results[0].presentation.options[0].id + ``` + +2. **Handling Multiple Plans**: + ```javascript + // Example of mapping through multiple plans + const plans = availablePlans.results[0].presentation.options.map(plan => ({ + id: plan.id, + name: plan.name, + price: plan.unit_amount / 100, // Convert cents to dollars + interval: plan.recurring.interval + })) + ``` + +3. **Checking Subscription Status**: + ```javascript + const subscriptions = await window.rownd.subscriptions.list() + const hasActiveSubscription = subscriptions.results.some( + sub => sub.status === 'active' || sub.status === 'trialing' + ) + ``` + +4. **Error Handling**: + ```javascript + try { + const response = await window.rownd.subscriptions.subscribe(subscriptionId, planId) + // Handle success + } catch (error) { + if (error.status === 402) { + // Handle payment required + } else if (error.status === 401) { + // Handle authentication error + } + // Handle other errors + } + ``` + +Remember: +- Always handle the case where a user has no active subscriptions +- Convert price amounts from cents to dollars for display +- Check authentication status before making API calls +- Handle loading states during API calls +- Provide clear error messages to users \ No newline at end of file diff --git a/rownd-docusaurus/docs/payments/overview.mdx b/rownd-docusaurus/docs/payments/overview.mdx new file mode 100644 index 0000000..0c92759 --- /dev/null +++ b/rownd-docusaurus/docs/payments/overview.mdx @@ -0,0 +1,74 @@ +--- +title: "Rownd Payments Overview" +sidebarTitle: "Overview" +--- + +Start accepting payments in your app within minutes, not months. Rownd Payments eliminates the complexity of payment processing, letting you focus on growing your business while we handle the technical and compliance details. + +## What You Get + +### Start Making Money in Seconds +- **Instant Setup**: Your payment account is created automatically - no lengthy applications or waiting periods +- **Zero Integration Hassle**: Skip months of payment provider documentation and complex API integrations +- **Ready-Made UI**: Beautiful payment components appear right in your app through the Rownd Hub + +### Everything Managed for You +- **One Dashboard**: View all your revenue, payouts, and customer payments in one place +- **Automatic Payouts**: Your money arrives in your bank account automatically - no manual transfers needed +- **Real-time Insights**: See exactly how your business is performing at any moment + +### Built for Your Success +- **Simple Integration**: Add payments to your app with just a few lines of code +- **Professional Checkout**: Your customers enjoy a seamless, branded payment experience +- **Flexible Products**: Create any type of product or subscription plan you need - we handle the complexity + +## Payment Providers Available to You + +Currently, you can process payments through: + +- **Stripe**: Industry-leading payment processing with global reach +- **More Coming Soon**: We're adding new providers based on your needs + +:::note +You pay just 1% on transactions. We cover all payment provider fees (including Stripe's processing fees) for transfers and payouts, so you keep more of what you earn. +::: + +## How to Get Started + +Getting paid is simple: + +1. Click "Enable Payments" in your Rownd dashboard +2. Add your business and bank details +3. Drop our payment components into your app +4. Start accepting payments immediately! + +## Perfect For + +### Subscription Businesses +- Monthly or annual billing for your SaaS +- Membership sites and communities +- Premium content subscriptions + +### Direct Sales +- Sell digital downloads +- Process one-time purchases +- Book appointments and services + +### Advanced Models +- Set up trial periods +- Offer promotional pricing +- Create custom billing cycles + +## Your Security is Handled + +We take care of all the complex security requirements: + +- **PCI Compliance**: We maintain it so you don't have to +- **Data Protection**: Your customers' payment information is always encrypted and secure +- **Fraud Prevention**: Built-in protection keeps your business safe +- **Full Compliance**: We handle all regulatory requirements for you + +## Your Next Steps + +- [Connect your Stripe account](/payments/stripe) +- [View detailed integration guide](/payments/app-setup) \ No newline at end of file diff --git a/rownd-docusaurus/docs/payments/stripe.mdx b/rownd-docusaurus/docs/payments/stripe.mdx new file mode 100644 index 0000000..ed852f2 --- /dev/null +++ b/rownd-docusaurus/docs/payments/stripe.mdx @@ -0,0 +1,116 @@ +--- +title: "Stripe Integration" +sidebarTitle: "Stripe Guide" +--- + +When you enable Rownd Payments, we automatically create and manage a Stripe Express account for you. This means you can start accepting payments immediately without dealing with Stripe's complex setup process or technical requirements. + +## Your Stripe Express Account + +Stripe Express is your gateway to accepting payments professionally. Here's what you get: + +- **Instant Activation**: Your account is ready to accept payments as soon as you enable it +- **Your Own Dashboard**: Access a clean, simple interface to manage your business +- **Daily Payouts**: Your earnings automatically transfer to your bank account every day +- **Full Control**: You own your customer relationships and set your own prices + +## What's Included + +### Automatic Setup - Done for You +- We create and configure your Stripe account instantly +- No forms to fill out or verification delays +- Start accepting payments right away + +### Everything in One Place +- See all your transactions in your Rownd dashboard +- Track payouts to your bank account +- View customer payment history and details + +### Professional Payment Experience +- Your customers see your brand, not ours +- Mobile-optimized checkout that works everywhere +- Secure payment processing they can trust + +### Simple Product Creation +- Create products and subscription plans in seconds +- Set any price or billing schedule you want +- We handle all the technical complexity + +## Getting Started + +1. **Turn on Payments** + - Go to the Payments section in your dashboard + - Click "Enable Stripe Payments" + - Complete a quick verification (takes 2 minutes) + +2. **Add Your Details** + - Enter your business information + - Connect your bank account for payouts + - Add your tax details (we'll help you) + +3. **Create Your First Product** + - Click "New Product" and follow the wizard + - Set your price and billing type + - Add a description your customers will see + +4. **Start Accepting Payments** + - Add our payment components to your app + - Customize how checkout looks + - Test everything before going live + +## Managing Your Money + +### Getting Paid +- Money arrives in your bank account daily +- See exactly when each payout will arrive +- Track every payment in real-time + +### Your Customers +- View complete payment history for each customer +- Process refunds with one click +- Handle any disputes that arise + +### Business Insights +- See your revenue growth over time +- Track which products perform best +- Understand your customer behavior + +## Tips for Success + +1. **Test Everything First** + - Use test mode to try different scenarios + - Make sure payments work smoothly + - Verify web hook connections are working + +2. **Stay on Top of Things** + - Check your dashboard regularly + - Address failed payments quickly + - Respond to customer questions promptly + +3. **Keep Everything Current** + - Update your business info when it changes + - Keep your bank details accurate + - Ensure tax information stays current + +## Common Questions + +### Payment Issues +- **Card Declined**: The customer needs to check their card details or try another card +- **Payout Delayed**: Verify your bank information is correct (payouts typically take 2-3 business days) +- **Integration Problems**: Make sure you're using the latest Rownd components + +## Need Help? + +If you run into any issues: + +1. Check our [documentation](/docs) for answers +2. Reach out to our support team - we're here to help +3. Check [Stripe's status](https://status.stripe.com) if payments aren't working + +## What's Next + +- [Set up your products](/payments/configuration) +- [Create subscription plans](/payments/products) +- [Customize your checkout](/payments/integration) +- [View your earnings](/payments/payouts) +- [View detailed integration guide](/payments/app-setup) \ No newline at end of file diff --git a/rownd-docusaurus/docs/security/SOC2-type2.mdx b/rownd-docusaurus/docs/security/SOC2-type2.mdx new file mode 100644 index 0000000..23873d4 --- /dev/null +++ b/rownd-docusaurus/docs/security/SOC2-type2.mdx @@ -0,0 +1,32 @@ +--- +title: SOC 2 Type 2 certification +description: Learn about Rownd's SOC 2 Type 2 certification and how it benefits your organization. +--- + +# Rownd's SOC 2 Type 2 certification + +![SOC 2 Type 2 Certified](/images/SOC2_badge.webp) + +At Rownd, we prioritize the security and privacy of your data. We are proud to announce that we have achieved SOC 2 Type 2 certification. This milestone demonstrates our commitment to maintaining the highest standards of security and compliance, ensuring that your sensitive information is protected. + +## What is SOC 2 Type 2 certification? + +SOC 2 (System and Organization Controls 2) is a rigorous auditing standard developed by the American Institute of CPAs (AICPA). It focuses on five key trust service principles: security, availability, processing integrity, confidentiality, and privacy. SOC 2 Type 2 certification specifically evaluates the operational effectiveness of these controls over a period of time, typically six months or more. + +### What this means for you + +- **Enhanced security**: Our SOC 2 Type 2 certification assures you that we have robust controls in place to protect your data. +- **Compliance simplification**: Leveraging our SOC 2 certification can simplify your own compliance efforts, reducing the complexity and time required for your audits. +- **Trust and credibility**: Partnering with a SOC 2 Type 2 certified provider like Rownd enhances your credibility and builds trust with your customers. + +## Moving forward + +At Rownd, our commitment to security and compliance is ongoing. We continuously monitor and enhance our security practices to stay ahead of emerging threats and ensure the highest standards of data protection. + +### Get in touch + +If you have any questions about our SOC 2 Type 2 certification or if you would like to discuss how Rownd can support your compliance efforts, please [contact us](mailto:support@rownd.io). We are here to help you every step of the way. + +Thank you for trusting Rownd with your data security needs. + + diff --git a/rownd-docusaurus/docs/security/attack-mitigation/bot-detection.mdx b/rownd-docusaurus/docs/security/attack-mitigation/bot-detection.mdx new file mode 100644 index 0000000..f6de1eb --- /dev/null +++ b/rownd-docusaurus/docs/security/attack-mitigation/bot-detection.mdx @@ -0,0 +1,14 @@ +--- +description: Bots already hate passwordless +--- + +Bot detection helps protect against scripted attacks by identifying requests that are likely coming from bots. This method of protection is effective against certain types of attacks while minimizing inconvenience to legitimate users. + +Rownd uses an invisible, rotating challenge to bring top-of-the-line bot detection to your app and website. Bots or human actors that fail the challenge are denied entry, so new users are not created. This protection focuses on sign-ins using email or SMS, since these are the most vulnerable to attack from bots. + +Sign-in with Google and Sign-in with Apple both have their own bot detection and security that adds additional layers of protection. + +### Enabling bot protection +It's enabled for all Rownd applications. + +Please [contact us](mailto:support@rownd.io?subject=Info%20on%20bot%20detection) if you would like to learn more about bot protection! \ No newline at end of file diff --git a/rownd-docusaurus/docs/security/attack-mitigation/domain-allow-list.mdx b/rownd-docusaurus/docs/security/attack-mitigation/domain-allow-list.mdx new file mode 100644 index 0000000..60cd2c6 --- /dev/null +++ b/rownd-docusaurus/docs/security/attack-mitigation/domain-allow-list.mdx @@ -0,0 +1,29 @@ +--- +title: "Domain allow-listing" +sidebarTitle: "Domain allow-listing" +description: "To prevent credential hijacking, Rownd recommends that customers set their list of allowed domains" +--- + +Domain allow-listing is a security feature in Rownd that provides an additional layer of protection for your application. By specifying a list of approved domains, you can ensure that Rownd only authenticates users from the designated websites. This helps prevent unauthorized access attempts and keeps your user data secure. By using domain allow-listing in Rownd, you can take greater control over your app's security, giving you and your users peace of mind. + +## Configuring the domain allow-list + +1. Open your app in the [Rownd platform](https://app.rownd.io/applications). Select **Settings** from the left sidebar. + + ![Finding Settings is easy; just select "Settings" from the HOME screen.](/images/settings-page.png) + +2. Locate the **URL(s) you are installing Rownd on** section +3. Enter the domains where you are installing Rownd with a "," between each. Please include any dev, test, and prod domains where Rownd may be installed. + + + Be sure to include all subdomians including `www` if applicable. + + + + Althogh Rownd may load on non-allow-listed sites, users will not be able to authenticate. + + +## Finishing up + +Once you have completed adding domains, press **Save Edits** to ensure your domain list is saved. + diff --git a/rownd-docusaurus/docs/security/attack-mitigation/overview.mdx b/rownd-docusaurus/docs/security/attack-mitigation/overview.mdx new file mode 100644 index 0000000..98c4200 --- /dev/null +++ b/rownd-docusaurus/docs/security/attack-mitigation/overview.mdx @@ -0,0 +1,37 @@ +--- +title: "Rownd Security" +sidebarTitle: "Overview" +description: + "How Rownd protects your users. " +--- + +Rownd can detect attacks and stop malicious attempts to access your application by blocking traffic from offending IPs, preventing SMS abuse attacks, and utilizing advanced (and invisible) human-verification technology. + +We provide the following services automatically, since protecting user data and ensuring your app is always ready for new and returning users is part of our core platform. + +- 100% Passwordless +- Suspicious IP Throttling +- Brute Force Protection +- Domain Allow-listing +- Data Encryption + +### Why passwordless matters + +Rownd is 100% passwordless. Most users re-use passwords, which increases the risk of data breaches and exposes users to various threats. Complex password rules and recommendations for unique passwords are often ignored, making it even more crucial to consider a passwordless solution. + +Passwordless authentication reduces the risks associated with traditional password-based authentication, such as brute force attacks, phishing attacks, and breached password databases. This approach not only enhances security but also provides a better user experience. + +Apps and companies that still rely on passwords as a primary factor of authentication should strongly reconsider their approach, as they put themselves and their customers at risk. By adopting Rownd's passwordless solution, you can ensure a secure and user-friendly authentication experience. + + +### Preventing fake users, phishing, and breaches + +Rownd advocates for a multi-layered approach to combat abuse, using various signals to detect and prevent attacks. We deliver this automatically for all customers. There's no need to pay extra for peace of mind. + +| Feature | Attack signal/vector | How it works | +| --- | --- | --- | +| [Suspicious IP Throttling](/security/attack-mitigation/suspicious-ip-throttling) | Rate of sign in attempts from a client. | Automatically throttles clients that try to sign up or sign in too quickly. Also automatically de-duplicates emails and text messages from similar sign-in attempts to reduce costs. | +| Brute Force Protection | N/A | Passwordless means reduced risk of brute-force attacks. | +| Passwordless Sign-in | Breached passwords | Passwordless means no breached passwords. | +| [Domain Allow-listing](/security/attack-mitigation/domain-allow-list) | Credential hijacking | Rownd provides a domain allow-list option, creating a critical extra layer of security. Every customer should use this in production. | +| Data Encryption | In-transit data capture | Rownd uses encryption in databases and adheres to state-of-the-industry best practices, such as SSL, database encryption, and other techniques to secure user data. | diff --git a/rownd-docusaurus/docs/security/attack-mitigation/suspicious-ip-throttling.mdx b/rownd-docusaurus/docs/security/attack-mitigation/suspicious-ip-throttling.mdx new file mode 100644 index 0000000..61a51f5 --- /dev/null +++ b/rownd-docusaurus/docs/security/attack-mitigation/suspicious-ip-throttling.mdx @@ -0,0 +1,10 @@ +--- +title: Suspicious IP throttling +description: "Automatic and always learning" +--- + +To protect your applications from high-velocity attacks targeting multiple accounts, Rownd uses suspicious IP throttling to block traffic from any IP that rapidly attempts too many sign-ins or sign-ups. + +This feature is automatically enabled when you create a Rownd app. If Rownd detects a large number of sign-up or sign-in attempts from a single IP address, it will temporarily block further attempts from that IP. + +We do not disclose our throttling strategy since they change depending on the threat environment. If you'd like to modify your settings, please [contact us](mailto:support@rownd.io?subject=Adjust%20IP%20throttling). \ No newline at end of file diff --git a/rownd-docusaurus/docs/security/hipaa-ready.mdx b/rownd-docusaurus/docs/security/hipaa-ready.mdx new file mode 100644 index 0000000..4620c59 --- /dev/null +++ b/rownd-docusaurus/docs/security/hipaa-ready.mdx @@ -0,0 +1,26 @@ +--- +title: HIPAA readiness +description: Learn about Rownd's HIPAA readiness and how it benefits your organization. +--- + +# Rownd's HIPAA readiness + +At Rownd, we understand the importance of compliance in the healthcare sector and are proud to announce that we are HIPAA ready. The Health Insurance Portability and Accountability Act (HIPAA) sets the standard for protecting sensitive patient data, and we are prepared to sign Business Associate Agreements (BAAs) to ensure that your data is handled in accordance with HIPAA regulations. + +## What is HIPAA readiness? + +HIPAA readiness means that we have implemented the necessary safeguards and protocols to protect Protected Health Information (PHI). This includes administrative, physical, and technical safeguards designed to ensure the confidentiality, integrity, and availability of PHI. + +### Benefits of HIPAA readiness + +- **Protected Health Information (PHI) security**: Our HIPAA readiness ensures that PHI is safeguarded with the highest security measures. +- **Regulatory compliance**: Partnering with Rownd helps you meet HIPAA requirements, reducing the risk of regulatory fines and penalties. +- **Peace of mind**: Knowing that your data is managed by a HIPAA-ready provider gives you confidence in your compliance posture. + +## Moving forward + +At Rownd, our commitment to security and compliance is ongoing. We continuously monitor and enhance our security practices to stay ahead of emerging threats and ensure the highest standards of data protection. + +### Get in touch + +If you have any questions about our HIPAA readiness or if you would like to discuss how Rownd can support your compliance efforts, please [contact us](mailto:support@rownd.io). We are here to help you every step of the way. diff --git a/rownd-docusaurus/docs/security/overview.mdx b/rownd-docusaurus/docs/security/overview.mdx new file mode 100644 index 0000000..edfb99e --- /dev/null +++ b/rownd-docusaurus/docs/security/overview.mdx @@ -0,0 +1,16 @@ +When it comes to authentication, security is paramount. Rownd takes the security of your data seriously. We use industry-standard encryption to protect your data in transit and at rest. We limit access to production environments to only those who need it in order to operate the service. We also provide controls to make it easier for you to secure your apps and websites against fraud and unauthorized access. + +Here are a few of the ways Rownd secures our platform and your products. + + + + + + + \ No newline at end of file diff --git a/rownd-docusaurus/docs/security/responsible-disclosure.mdx b/rownd-docusaurus/docs/security/responsible-disclosure.mdx new file mode 100644 index 0000000..80ca9c0 --- /dev/null +++ b/rownd-docusaurus/docs/security/responsible-disclosure.mdx @@ -0,0 +1,9 @@ +We take the security of our users' data very seriously. If you believe you have discovered a security vulnerability in any of our products or services, we encourage you to report it to us as quickly as possible. We will investigate all legitimate reports and do our best to quickly fix the problem. + +Please submit your report to [security@rownd.com](mailto:security@rownd.com?subject=%5BSecurity%20vulnerability%20submission%5D%20ADD%20YOUR%20SUBJECT%20HERE). We aim to acknowledge receipt of your report within 24 hours. + +We ask that you do not publicly disclose the issue until we have had a chance to address it. We will keep you informed of our progress throughout the process. + +### Bug bounties + +At this time, we generally do not offer bug bounties for reported vulnerabilities. Please refer to this page for updates. diff --git a/rownd-docusaurus/docs/welcome/comparisons/auth0.mdx b/rownd-docusaurus/docs/welcome/comparisons/auth0.mdx new file mode 100644 index 0000000..47236ae --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/auth0.mdx @@ -0,0 +1,154 @@ +--- +title: "Rownd vs Auth0" +sidebarTitle: "Auth0" +--- +When evaluating comprehensive application services platforms, understanding the key differences between options is essential. This comparison highlights how Rownd's AI-enabled Application Services Platform offers unique advantages over Auth0's authentication-focused service, particularly for teams requiring complete app services including payments, smart links, and AI-powered optimization. + +## Rownd: AI-Enabled Application Services Platform + +Rownd has evolved beyond authentication to become a complete application services platform: + +**🤖 AI-Powered Intelligence** - Rownd leverages AI to optimize every aspect of your app's services. From intelligent authentication flows that adapt to user behavior to predictive analytics and automated A/B testing, our AI engine continuously improves conversion rates and user experience without manual intervention. + +**💳 Integrated Payments** - Unlike Auth0, Rownd includes built-in payment processing powered by Stripe. Launch subscriptions, accept payments, and manage billing—all from the same platform that handles your authentication. Just 1% platform fee with all Stripe fees covered. + +**🔗 Smart Links & Deep Linking** - Create intelligent, trackable links that work across web and mobile. Perfect for marketing campaigns, user onboarding, and re-engagement—a complete feature set Auth0 doesn't offer. + +**📱 Complete App Services** - Beyond authentication, Rownd provides email/phone verification, app onboarding support, user management, and more—all controllable from one unified dashboard without redeployment. + +## Feature Comparison + +| Feature | Rownd | Auth0 | Rownd Advantage | +|---------|-------|-------|-----------------| +| **Platform Scope** | Complete Application Services Platform: auth, payments, smart links, verification, user management | Authentication and authorization service with basic user management | Rownd eliminates the need for multiple services, providing everything modern apps need in one platform | +| **[Payments Integration](/payments/overview)** | Built-in Stripe integration with automatic account setup, subscription management, payment UI components, 1% fee (Stripe fees covered) | No payment capabilities - requires separate payment service integration | Start accepting payments in minutes without wrestling with Stripe APIs or building custom checkout flows | +| **[Smart Links](/magic-links/overview)** | Full smart links platform with analytics, deep linking, QR codes, custom domains, campaign tracking | Basic email magic links for authentication only | Drive users to any part of your app across platforms, track campaigns, and maintain context through authentication | +| **AI-Powered Features** | Intelligent flow optimization, predictive analytics, automated A/B testing, smart routing, fraud detection | Limited to basic threat detection and anomaly detection | AI continuously optimizes your entire user experience, improving conversion rates by 30-40% automatically | +| **Pricing Model** | Free up to 1 million users, transparent usage-based pricing, includes all services | Complex pricing tiers starting at $240/month for 1,000 users, enterprise pricing opaque | Rownd's generous free tier and simple pricing makes it 10-100x more cost-effective for most applications | +| **[Security & Compliance](/security/overview)** | [SOC 2 Type II certified](/security/SOC2-type2), [HIPAA-ready](/security/hipaa-ready), GovCloud approved, military-grade security controls, PCI compliant for payments | SOC 2 Type II, ISO 27001, HIPAA BAA available, limited military approval | Rownd provides immediate compliance readiness for both identity and payment data without extensive configuration | +| **[Authentication Methods](/configuration/authentication-methods/overview)** | Modern, password-less: [email links](/configuration/authentication-methods/email), [SMS OTP](/configuration/authentication-methods/phone-sms), social login, [passkeys](/configuration/authentication-methods/passkeys), [guest users](/configuration/authentication-methods/guests), [instant users](/configuration/authentication-methods/instant-users) | Traditional username/password first, with password-less options requiring additional configuration, limited guest access | Rownd's password-less first approach eliminates friction and security risks while enabling true zero-friction initial engagement | +| **[In-Context Authentication](/configuration/customizations/global-style)** | Seamless in-app/in-context authentication maintains user flow without disruptive redirects | Requires redirects to Auth0-hosted pages or significant custom development | Keeping users in context during authentication increases conversion rates by 30-40% and reduces bounce rates | +| **[User Management](/configuration/user-accounts/overview)** | Complete user lifecycle management with profiles, groups, progressive profiling, self-service portals | Basic user profile storage, limited progressive profiling capabilities | Rownd provides everything needed for user management without additional services or custom development | +| **Email/Phone Verification** | Built-in verification services with custom branding, retry logic, deliverability optimization | Basic email verification, SMS requires additional configuration and providers | Complete verification solution included with intelligent retry and deliverability features | +| **Development Speed** | Hours to implement complete app services, zero backend configuration | Days or weeks for authentication alone, additional time for other services | Launch complete app services 10x faster with Rownd's all-in-one platform | +| **[No-Code Capabilities](/configuration/automations/overview)** | 95% of customizations via dashboard: flows, UI, payments, links, automations | Limited no-code options, most changes require code deployment | Empower product and marketing teams to iterate without engineering bottlenecks | +| **[Mobile Support](/sdk-reference/mobile/overview)** | Comprehensive native SDKs with payment UI, deep linking, complete feature parity | Limited mobile SDKs focused on authentication only | Complete mobile app services with native experiences across all features | + +## Key Advantages of Rownd's Platform Approach + +### 1. Complete App Services vs. Authentication Only + +Rownd provides everything modern applications need: + +- **Authentication & User Management**: Complete user lifecycle from first visit to loyal customer +- **Payments**: Accept payments and manage subscriptions without additional services +- **Smart Links**: Drive users anywhere in your app with trackable, intelligent links +- **Verification**: Email and phone verification built-in +- **Analytics**: Understand user behavior across all services + +Auth0 requires stitching together multiple services to achieve what Rownd provides out of the box. + +### 2. AI-Powered Optimization + +Rownd's AI engine works across all services: + +- Automatically optimizes authentication flows based on user behavior +- Predicts and prevents payment failures +- Routes users through smart links to maximize conversion +- Continuously A/B tests without manual configuration +- Provides actionable insights across the entire user journey + +Auth0's limited AI capabilities focus only on security, missing opportunities to improve user experience and conversion. + +### 3. Integrated Payments - A Game Changer + +Rownd's payment integration eliminates complexity: + +- Automatic Stripe Express account creation +- Pre-built payment UI components +- Subscription management built-in +- Just 1% platform fee with Stripe fees covered +- PCI compliance handled automatically + +Adding payments to Auth0 requires separate services, custom integration, and months of development. + +### 4. Smart Links for Growth + +Rownd's smart links enable powerful growth strategies: + +- Create links that work across web, iOS, and Android +- Track campaign performance with built-in analytics +- Deep link users to any app state +- Maintain context through authentication +- Use custom domains for branded experiences + +Auth0's basic magic links pale in comparison to Rownd's comprehensive linking platform. + +### 5. True No-Code Platform Management + +Rownd empowers entire teams without code: + +- Launch new payment products from the dashboard +- Create and track marketing campaigns with smart links +- Modify authentication flows instantly +- Customize all UI components visually +- Set up automations without engineering + +Auth0's dependence on code changes creates bottlenecks and slows innovation. + +### 6. Cost-Effective at Scale + +Rownd's pricing model is revolutionary: + +- **Free up to 1 million users** (Auth0 charges from 1,000 users) +- Simple, transparent pricing beyond free tier +- All services included (auth, payments, links, etc.) +- No hidden fees or complex calculations +- 10-100x more cost-effective for most applications + +Auth0's pricing quickly becomes prohibitive, especially when adding other services. + +### 7. Faster Time to Market + +With Rownd, launch complete app services in hours: + +- One SDK installation covers all services +- Pre-built UI components for everything +- No backend configuration required +- Instant customization via dashboard +- Start accepting payments immediately + +Auth0 alone takes days to properly configure, and that's before adding other services. + +### 8. Unified Analytics & Insights + +Rownd provides comprehensive analytics across all services: + +- User journey from first visit through payment +- Authentication conversion rates +- Payment success metrics +- Smart link performance +- All in one unified dashboard + +With Auth0, you need separate analytics for each service, making it difficult to understand the complete picture. + +## When to Choose Rownd + +Rownd is the clear choice for: + +1. **Modern applications** needing more than just authentication +2. **Startups and scale-ups** wanting to launch quickly without technical debt +3. **Teams with limited resources** who need one platform instead of many +4. **Growth-focused companies** leveraging smart links and AI optimization +5. **SaaS applications** requiring integrated payment processing +6. **Mobile-first products** needing complete services across platforms +7. **Cost-conscious teams** taking advantage of 1M free users +8. **AI-driven development** using VIBE coding and modern workflows + +## Summary + +While Auth0 remains a solid authentication provider, it's just one piece of what modern applications need. Rownd's AI-enabled Application Services Platform provides authentication, payments, smart links, and more—all in one platform that's free up to 1 million users. + +By choosing Rownd, you eliminate the complexity of integrating multiple services, reduce costs dramatically, and gain access to AI-powered optimization that continuously improves your application. With faster implementation, better user experiences, and comprehensive features, Rownd represents the future of application services—delivering everything you need to build, launch, and scale successful applications. + +For teams ready to move beyond piecemeal solutions to a unified platform that grows with them, Rownd provides the complete answer Auth0 simply can't match. \ No newline at end of file diff --git a/rownd-docusaurus/docs/welcome/comparisons/clerk.mdx b/rownd-docusaurus/docs/welcome/comparisons/clerk.mdx new file mode 100644 index 0000000..d541f1e --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/clerk.mdx @@ -0,0 +1,173 @@ +--- +title: "Rownd vs Clerk" +sidebarTitle: "Clerk" +--- + +When evaluating comprehensive user management solutions for your application, understanding the key differences between options is essential. This comparison highlights how Rownd's complete user management platform offers unique advantages over Clerk, particularly for teams requiring full user lifecycle management, no-code customization, and enterprise-grade security. + +## Rownd: Complete User Management for Modern Development + +Rownd stands apart as a complete user management platform specifically engineered for today's development landscape: + +**🤖 AI-Ready & VIBE Optimized** - Rownd is designed from the ground up to work seamlessly with AI tools and VIBE (Visual Integrated Development Experiences) workflows. With well-documented patterns, consistent APIs, and dashboard-configurable options, Rownd dramatically reduces the complexity AI assistants need to navigate, enabling 50-70% faster implementation with minimal security risks. + +**📱 Truly Mobile-First** - Unlike solutions that prioritize web then add mobile support, Rownd provides complete feature parity across platforms with native SDKs for iOS, Android, React Native, Flutter, and Expo alongside optimized web experiences. This unified architecture ensures users enjoy a consistent, native-feeling experience across all their devices. + +**🔄 100% Dynamic User Management** - Rownd's platform lets you modify nearly every aspect of your user management flows without code changes or redeployments. With 95% of customizations available directly from the dashboard, product teams can test, iterate, and optimize the entire user experience in real-time rather than waiting for engineering resources. + +## Feature Comparison + +| Feature | Rownd | Clerk | Rownd Advantage | +|---------|-------|-------|-----------------| +| **[Login Methods](/configuration/authentication-methods/overview)** | Supports OIDC login with [Google](/configuration/authentication-methods/google), [Apple](/configuration/authentication-methods/apple), biometric [Passkeys](/configuration/authentication-methods/passkeys), magic links ([email](/configuration/authentication-methods/email) & [SMS](/configuration/authentication-methods/phone-sms)), plus any [OIDC-compliant provider](/configuration/authentication-methods/oauth) (Login.gov, Air Force, SAML) | Email/password, magic links, social logins (Google, GitHub, Apple), built-in MFA options | Rownd's full OIDC server lets you plug in specialized government/military identity providers and manage them centrally—no custom code required | +| **[User Management](/configuration/user-accounts/overview)** | [Instant Users](/configuration/authentication-methods/instant-users) assign a unique Rownd ID to every visitor, self-service profiles, unified account across methods, API & dashboard user admin | Prebuilt user profile UI, team/org management with roles, invitations, impersonation mode | Rownd preserves user context from first visit (no duplicate accounts) and offers dynamic grouping rules via dashboard or API | +| **[UI Out-of-the-Box](/configuration/customizations/global-style)** | Ready-to-use, customizable visual components across 12+ SDKs, no-code theming via dashboard | React/Next components, dedicated pages, modal-based flows—requires front-end integration and redeploys for UI changes | Rownd's UI can be entirely branded and iterated from the platform without touching code—mobile and web share the same control plane | +| **[Profile Management](/configuration/user-accounts/user-profiles)** | Dynamic custom fields, [progressive profiling](/configuration/user-accounts/progressive-profiles), conditional inputs, self-service edits via dashboard or API | Profile editing hooks and UI, but schema changes demand front-end work | Schema updates and field logic in Rownd happen in minutes—no PRs or deployments needed | +| **Session Management** | Automatic session handling, JWT revocation, built-in analytics, dashboard controls for logout behavior and session limits | Session management via httpOnly cookies, client hooks (`useSession()`), and basic session APIs—limited out-of-the-box analytics | Rownd provides real-time session metrics and dynamic revocation rules from the dashboard, ideal for high-security environments | +| **[Smart Links](/magic-links/overview)** | Dynamic deep links for onboarding, re-engagement, multi-platform sign-in; campaign targeting & upcoming analytics dashboard | N/A | Unique feature: Smart Links let you drive users into any step of your flow across web and apps without building separate landing pages | +| **Custom Domains** | Native support for first-party custom domains on auth flows, magic links, and emails (coming soon) | Custom domains & subdomains configurable via dashboard/API; SSL automation and key rotation management | Rownd's upcoming custom-domain rollout will tie directly into Smart Links and branding, offering a seamless, fully white-label experience | +| **[OIDC Server](/configuration/oidc/overview)** | Full OpenID Connect provider: metadata, JWK set, token, introspection, and revocation endpoints | Acts as OIDC IdP/consumer for federated login, but no exposed introspection or revoke endpoints | Rownd exposes the complete OIDC control plane for federation, token governance, and multi-tenant federation via standard endpoints | +| **[Integrations & APIs](/configuration/integrations/overview)** | Web hooks, REST APIs, full backend SDKs ([.NET](/sdk-reference/web/net-core), [Go](/sdk-reference/web/go), [Django](/sdk-reference/web/django--python), [Node](/sdk-reference/web/node-js), etc.), CRM connectors ([HubSpot](/configuration/integrations/hubspot), [Air table](/configuration/integrations/airtable), [MailerLite](/configuration/integrations/mailerlite)), Web3 (NEAR) | Web hooks, REST APIs, OIDC integrations, CRM plugins (Stripe, other databases), limited Web3 support | Rownd's catalog covers more "no-code" CRM syncs and blockchain onboarding out of the box, reducing custom integration work | +| **[Compliance & Security](/security/overview)** | [SOC 2 Type II certification](/security/SOC2-type2), [HIPAA-ready](/security/hipaa-ready), industry-standard encryption in transit & at rest | SOC 2 Type II, CCPA & GDPR compliance | Rownd's HIPAA readiness and dedicated security controls meet both healthcare and military-grade requirements | +| **Dynamic Authentication** | Instant, no-code flow modifications via dashboard; adaptive sign-in ordered per device (desktop/iOS/Android) | Pre-built React/Next UI components (SignIn, SignUp, etc.) require code changes or redeploys to adjust flows | Rownd lets you tweak authentication logic in real time without touching code | +| **[No-Code Automations](/configuration/automations/overview)** | Built-in [automations for sign-in prompts](/configuration/automations/sign-in-prompt), passive data collection, promotional opt-ins, passkey enrollment—all configurable in the dashboard without code | Web hooks for event notifications only; lacks a user-friendly automation builder | Rownd empowers non-dev teams to launch, A/B-test, and iterate onboarding automations instantly | +| **Programmatic Control** | API-first with event hooks and full backend SDK support for programmatic adjustments to auth, user profiles, and configurations | APIs & web hooks for user management, but no native programmatic flow-control plane or agent integration | Rownd's control plane enables AI agents or scripts to adjust flows, groups, and automations on the fly | +| **[UI Customization](/configuration/customizations/global-style)** | Global style dashboard—colors, logos, corner radii, light/dark modes, illustrations, overlays, sub-brands—all no-code | Pixel-perfect UI components customizable via CSS and theming, but changes require front-end work | Rownd's dashboard puts complete design control in product/marketing hands—no developer support needed | +| **[Multi-Platform Support](/sdk-reference/overview)** | 12+ SDKs covering Web ([React](/sdk-reference/web/react), [Next](/sdk-reference/web/nextjs), [Angular](/sdk-reference/web/angular), multiple frameworks, etc.), Mobile ([iOS](/sdk-reference/mobile/ios), [Android](/sdk-reference/mobile/android), [Flutter](/sdk-reference/mobile/flutter), [React Native](/sdk-reference/mobile/react-native), [Expo](/sdk-reference/mobile/expo)), Backend ([Node](/sdk-reference/web/node-js), [Django](/sdk-reference/web/django--python), [.NET](/sdk-reference/web/net-core), [Go](/sdk-reference/web/go)), plus [Web3](/configuration/web3/near-overview) (NEAR) | SDKs for React, Next, Astro, Remix, iOS & Android; no native Web3 wallet support | Rownd extends beyond traditional apps into blockchain onboarding, plus broader backend framework support | +| **[Group Management](/configuration/user-accounts/groups)** | Role-based access, dynamic group assignment rules, automated group logic—all configurable via dashboard or API | Organization & multi-tenant support with role assignment, but lacks dynamic assignment rules; group changes require API calls | Rownd's dynamic group rules simplify access control and reduce misconfiguration risk | +| **[Progressive Profiling](/configuration/user-accounts/progressive-profiles)** | Trigger controls, progressive profiling steps, and conditional flows—all built into the dashboard | Offers multi-step sign-up components, but additional profiling requires custom code; no built-in conditional logic UI | Rownd accelerates data collection and personalization without dev cycles | + +## Key Advantages of Rownd Over Clerk + +### 1. No-Code Flexibility + +Rownd provides dashboard-based controls for virtually every aspect of authentication and user management. Unlike Clerk, which requires code changes and redeployments for most customizations, Rownd allows product teams to: + +- Modify [authentication flows](/configuration/authentication-methods/overview) on the fly +- Change [UI components and styling](/configuration/customizations/global-style) without developer involvement +- Create and adjust [profiling steps](/configuration/user-accounts/progressive-profiles) instantly +- Configure [automations](/configuration/automations/overview) without writing code + +This translates to faster iteration cycles and reduced engineering overhead. + +### 2. Enterprise-Ready Security & Compliance + +While both platforms offer SOC 2 Type II certification, Rownd goes further with: + +- [HIPAA readiness](/security/hipaa-ready) for healthcare applications +- [Military-grade security controls](/security/overview) +- Complete session visibility and management +- Comprehensive token governance via [OIDC endpoints](/configuration/oidc/overview) + +These features make Rownd suitable for the most security-sensitive industries and use cases. + +### 3. Unified Cross-Platform Experience + +Rownd's platform provides consistent authentication experiences across: + +- [Web applications](/sdk-reference/web/overview) (all major frameworks) +- [Mobile applications](/sdk-reference/mobile/overview) (native and cross-platform) +- [Backend services](/sdk-reference/backend/overview) +- [Web3 applications](/configuration/web3/near-overview) + +This unified approach ensures users have the same seamless experience regardless of how they access your application, while Clerk has more limited platform support. + +### 4. Unique Features Missing in Clerk + +Several Rownd capabilities have no equivalent in Clerk: + +- **[Smart Links](/magic-links/overview)**: Create targeted deep links for onboarding and re-engagement +- **[Instant Users](/configuration/authentication-methods/instant-users)**: Preserve user context from first anonymous visit through conversion +- **[No-Code Automations](/configuration/automations/overview)**: Visual builder for authentication prompts and data collection +- **[Dynamic Group Rules](/configuration/user-accounts/groups)**: Automatically assign users to groups based on behavior or attributes + +### 5. Military-Grade Security for Sensitive Environments + +Rownd's [security posture](/security/overview) isn't just marketing—it's battle-tested with actual military contracts. Unlike Clerk, Rownd's authentication platform is: + +- Deployed in active military environments +- Designed to meet DoD security standards +- Built with FedRAMP-aligned security controls +- Capable of integrating with specialized [government identity providers](/configuration/authentication-methods/oauth) + +For regulated sectors and defense contractors, Rownd's proven military-grade security provides peace of mind that civilian-focused alternatives simply can't match. + +### 6. Truly Dynamic Authentication (95% Dashboard-Configurable) + +While most auth providers require code changes for customization, Rownd stands apart with 95% of authentication customizations available directly from the dashboard: + +- Change [sign-in methods](/configuration/authentication-methods/overview) without deployment +- Adjust authentication flows per platform ([web](/sdk-reference/web/overview) vs [mobile](/configuration/mobile/overview)) +- Modify prompts and messaging instantly +- A/B test different authentication experiences +- Configure conditional logic based on user attributes + +This dynamic approach dramatically reduces the engineering overhead typically associated with authentication changes. + +### 7. Comprehensive Mobile SDK Coverage + +Rownd's [mobile coverage](/sdk-reference/mobile/overview) significantly outpaces Clerk with: + +- Native [iOS](/sdk-reference/mobile/ios) and [Android](/sdk-reference/mobile/android) SDKs with complete feature parity +- Cross-platform support via [React Native](/sdk-reference/mobile/react-native), [Flutter](/sdk-reference/mobile/flutter), and [Expo](/sdk-reference/mobile/expo) +- Consistent UX between mobile apps and web interfaces +- Mobile-specific authentication optimizations (biometric, deep linking) +- Complete [UI customization](/configuration/customizations/global-style) from a single dashboard + +For companies with mobile apps, Rownd eliminates the need to build, maintain, and synchronize separate authentication systems. + +### 8. Visual-Based SDKs Across Platforms + +Rownd's visual SDKs dramatically reduce development time across all platforms: + +- Pre-built UI components that inherit [global styling](/configuration/customizations/global-style) +- Dynamic form generation based on [profile schemas](/configuration/user-accounts/user-profiles) +- Adaptive layouts that optimize for device characteristics +- Built-in accessibility and internationalization +- Form validation and error handling included + +These visual components handle 80% of typical user management UI work out-of-the-box, freeing developers to focus on core application features. + +### 9. AI Agent Integration (MCP Native) + +Rownd is uniquely positioned for the AI-driven development era with: + +- Complete [API access](/api-reference/authentication/overview) for AI agent manipulation +- Programmatic control over all authentication aspects +- Ability to adjust flows, [groups](/configuration/user-accounts/groups), and designs via AI +- Real-time configuration changes without human intervention +- Auditable trail of system changes made by AI agents + +This agent-centric architecture allows AI assistants to directly optimize and maintain authentication systems with minimal human oversight. + +### 10. VIBE Coding Advantage (AI Prompt-Driven Development) + +For teams using VIBE coding (AI prompt-based development), Rownd provides distinct advantages: + +- Well-documented, consistent [API patterns](/api-reference/authentication/overview) easily described in prompts +- Dashboard-configurable options reduce need for custom code +- Clean separation between auth logic and application code +- Standardized implementation patterns across platforms +- Simplified maintenance reducing technical debt + +This makes Rownd an ideal choice for AI-assisted development workflows, reducing the complexity AI needs to manage and minimizing the risk of configuration errors. + +## When to Choose Rownd + +Rownd is particularly well-suited for: + +1. **AI-driven development teams** using VIBE coding and agent-based workflows +2. **Mobile-first companies** needing [comprehensive native SDK support](/sdk-reference/mobile/overview) +3. **High-velocity teams** that need to iterate quickly without engineering bottlenecks +4. **Regulated industries** requiring advanced [security and compliance features](/security/overview) +5. **Cross-platform applications** needing consistent auth across [web](/sdk-reference/web/overview), [mobile](/sdk-reference/mobile/overview), and [backend](/sdk-reference/backend/overview) +6. **Product-led growth** initiatives leveraging [progressive profiling](/configuration/user-accounts/progressive-profiles) and [smart links](/magic-links/overview) +7. **Organizations with limited engineering resources** who need to empower product and marketing teams +8. **Military and government contractors** requiring specialized [security controls](/security/overview) + +## Summary + +While Clerk offers solid authentication capabilities, Rownd provides a more comprehensive, flexible platform with unique features that reduce engineering overhead and enable faster iteration. With its no-code dashboard, military-grade security, and innovative capabilities like [Smart Links](/magic-links/overview) and [Instant Users](/configuration/authentication-methods/instant-users), Rownd delivers a superior authentication solution for modern applications. + +Rownd's dynamic platform approach—where 95% of customizations happen without code—combined with its agent-ready architecture and comprehensive mobile support makes it the clear choice for forward-thinking development teams, especially those embracing AI-assisted workflows. + diff --git a/rownd-docusaurus/docs/welcome/comparisons/cognito.mdx b/rownd-docusaurus/docs/welcome/comparisons/cognito.mdx new file mode 100644 index 0000000..abc6b85 --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/cognito.mdx @@ -0,0 +1,154 @@ +--- +title: "Rownd vs Amazon Cognito" +sidebarTitle: "Cognito" +--- + +When evaluating comprehensive user management solutions for your application, understanding the key differences between options is essential. This comparison highlights how Rownd's complete user management platform offers unique advantages over Amazon Cognito, particularly for teams requiring full user lifecycle management, no-code customization, and rapid implementation without AWS expertise. + +## Rownd: Complete User Management for Modern Development + +Rownd stands apart as a complete user management platform specifically engineered for today's development landscape: + +**🤖 AI-Ready & VIBE Optimized** - Rownd is designed from the ground up to work seamlessly with AI tools and VIBE (Visual Integrated Development Experiences) workflows. With well-documented patterns, consistent APIs, and dashboard-configurable options, Rownd dramatically reduces the complexity AI assistants need to navigate, enabling 50-70% faster implementation with minimal security risks. + +**📱 Truly Mobile-First** - Unlike solutions that prioritize web then add mobile support, Rownd provides complete feature parity across platforms with native SDKs for iOS, Android, React Native, Flutter, and Expo alongside optimized web experiences. This unified architecture ensures users enjoy a consistent, native-feeling experience across all their devices. + +**🔄 100% Dynamic User Management** - Rownd's platform lets you modify nearly every aspect of your user management flows without code changes or redeployments. With 95% of customizations available directly from the dashboard, product teams can test, iterate, and optimize the entire user experience in real-time rather than waiting for engineering resources. + +## Feature Comparison + +| Feature | Rownd | Amazon Cognito | Rownd Advantage | +|---------|-------|-------|-----------------| +| **[Security & Compliance](/security/overview)** | [SOC 2 Type II certified](/security/SOC2-type2), [HIPAA-ready](/security/hipaa-ready), GovCloud approved, military-grade security controls | SOC compliant as part of AWS, HIPAA eligible, FedRAMP moderate | Rownd provides a dedicated authentication platform with security certifications specific to identity management rather than inherited from a cloud provider | +| **[Authentication Methods](/configuration/authentication-methods/overview)** | Modern, password-less: [email links](/configuration/authentication-methods/email), [SMS OTP](/configuration/authentication-methods/phone-sms), social login, [passkeys](/configuration/authentication-methods/passkeys), [guest users](/configuration/authentication-methods/guests), [instant users](/configuration/authentication-methods/instant-users) | Username/password focused with optional MFA, limited social providers, no guest or instant user options | Rownd's password-less approach increases conversion rates by 30-40% and reduces support tickets while enabling frictionless initial engagement | +| **[In-Context Authentication](/configuration/customizations/global-style)** | Seamless in-app/in-context authentication maintains user flow without disruptive redirects | Requires hosted UI with redirects or significant custom development | Keeping users in context during authentication reduces bounce rates and increases conversion by maintaining user flow | +| **[User Management](/configuration/user-accounts/overview)** | [Instant Users](/configuration/authentication-methods/instant-users) assign a unique Rownd ID to every visitor, unified account across methods, self-service profiles | User pool management requiring significant configuration, no concept of instant or anonymous users | Rownd preserves user context from first visit and enables progressive profiling, increasing signup completion by 50-75% | +| **[Universal Link Support](/magic-links/overview)** | Full [smart links](/magic-links/overview) implementation with deep linking across platforms | Basic authentication links, no universal linking framework | Smart Links let you drive users into any step of your flow across web and apps, maintaining context through authentication flows | +| **[Social & Government Authentication](/configuration/authentication-methods/overview)** | Native one-click support for [Google](/configuration/authentication-methods/google), [Apple](/configuration/authentication-methods/apple), Login.gov, AF Mobile Connect, and any OIDC provider | Limited social providers, complex setup for government identity providers | Rownd's pre-configured providers can be set up in under a minute, with significantly less configuration and testing time | +| **[Automations](/configuration/automations/overview)** | Time-based and page-based [automation triggers](/configuration/automations/overview), contextual authentication, device-based context | No built-in automation capabilities, requires Lambda functions | Rownd's contextual authentication triggers based on user behavior increase conversion rates without requiring custom code | +| **[UI Components](/sdk-reference/overview)** | Ready-to-use, customizable [visual components](/configuration/customizations/global-style) across 12+ platforms – web, mobile, cross-platform | Hosted UI with limited customization or significant custom development required | Rownd provides pre-built, customizable components for all platforms, reducing development time by 60-80% | +| **[Mobile-First Architecture](/sdk-reference/mobile/overview)** | Comprehensive native mobile libraries for [iOS](/sdk-reference/mobile/ios), [Android](/sdk-reference/mobile/android), [React Native](/sdk-reference/mobile/react-native), [Flutter](/sdk-reference/mobile/flutter), and [Expo](/sdk-reference/mobile/expo) with complete feature parity | Basic Amplify SDK requiring significant customization for native experiences | Rownd's mobile-first approach ensures seamless authentication experiences across all devices with 40-60% less development time | +| **[AI & VIBE Coding Support](/api-reference/authentication/overview)** | Well-documented APIs, consistent patterns easily described in prompts, dashboard-configurable options, clean separation between auth and app code | Complex configuration requiring AWS expertise, difficult to describe in AI prompts | Rownd is designed for AI prompt-based development with clear patterns that reduce complexity for AI tools and minimize configuration errors | +| **[Growth Features](/configuration/user-accounts/progressive-profiles)** | [Smart links](/magic-links/overview), cross-app authentication, customizable auth flow location, [dynamic user groups](/configuration/user-accounts/groups), [progressive profiling](/configuration/user-accounts/progressive-profiles) | No built-in growth-oriented features | Rownd enables frictionless user acquisition and optimized authentication placement, improving signup completion by 20-30% | +| **[Platform Management](/configuration/applications)** | Full-featured dashboard, user profile self-management portal, no-code admin interface | AWS Console with complex configuration screens, limited user-facing management tools | Rownd's admin tools reduce support tickets by 40-60% and enable non-technical teams to resolve user issues without developer involvement | +| **[Customization](/configuration/customizations/global-style)** | Visual authentication designer, no-code sign-in method addition, dynamic branding rules, [sub-brand management](/configuration/customizations/sub-brands) | Limited UI customization via CSS, requires Lambda triggers for custom workflows | Rownd allows non-technical teams to optimize authentication flows and maintain brand consistency without writing code | +| **Implementation Time** | Hours to implement, zero backend configuration | Days or weeks to configure properly, requires significant AWS expertise | Rownd dramatically reduces time-to-market with authentication that works out of the box | +| **Pricing Model** | Predictable usage-based pricing, no hidden infrastructure costs | Complex pricing based on MAUs, storage, Lambda executions, and other AWS services | Rownd provides transparent, predictable pricing without unexpected costs from associated AWS services | + +## Key Advantages of Rownd Over Amazon Cognito + +### 1. Dramatically Simplified Implementation + +Rownd provides an authentication solution that can be implemented in hours rather than days or weeks: + +- Drop-in SDKs that work immediately with minimal configuration +- No backend configuration or AWS expertise required +- Zero server-side setup or Lambda functions to maintain +- Automatic handling of token management and refresh +- Pre-built UI components requiring minimal customization + +Unlike Cognito's complex setup process that requires deep AWS knowledge, User Pool configuration, Lambda triggers, and hosted UI customization, Rownd works out of the box with sensible defaults while providing customization options through a user-friendly dashboard. + +### 2. Enterprise-Ready Security Without the Complexity + +Rownd's platform comes with immediate compliance capabilities: + +- [SOC 2 Type II certification](/security/SOC2-type2) dedicated to authentication services +- [HIPAA readiness](/security/hipaa-ready) for healthcare applications +- GovCloud approval for government deployments +- DoD-approved for military applications +- Robust security controls with continuous monitoring + +While Cognito inherits AWS's compliance certifications, Rownd's focused approach to authentication security provides advantages for regulated industries without the configuration complexity. + +### 3. Superior User Experience + +Rownd's platform provides authentication experiences designed for modern user expectations: + +- In-context authentication without disruptive redirects +- [Instant Users](/configuration/authentication-methods/instant-users) for immediate product exploration +- Persistent authentication across sessions and devices +- Seamless mobile authentication with biometric options +- Contextual, adaptive authentication based on user behavior + +Cognito's hosted UI requires redirects that disrupt user flow, or extensive custom development to build an equivalent experience. Rownd delivers a superior user experience out of the box. + +### 4. Growth-Oriented Features + +Rownd includes built-in capabilities designed to accelerate user acquisition and engagement: + +- [Smart Links](/magic-links/overview) for targeted deep linking across platforms +- Time and page-based [automation triggers](/configuration/automations/overview) +- [Progressive profiling](/configuration/user-accounts/progressive-profiles) for incremental data collection +- Authentication that can be embedded anywhere (blogs, marketing pages) +- Cross-app authentication for unified user experiences + +These growth-focused features enable product-led strategies that Cognito simply doesn't address without significant custom development. + +### 5. True Mobile-First Architecture + +Rownd was built from the ground up with mobile experiences in mind: + +- Native mobile libraries with platform-specific optimizations +- Complete feature parity between web and mobile implementations +- Biometric authentication deeply integrated with native capabilities +- Responsive components automatically adapting to any screen size +- Deep linking and universal navigation patterns across platforms + +While Cognito offers mobile SDKs through Amplify, they require significant customization and don't provide the same level of pre-built, native components that Rownd offers. + +### 6. AI & VIBE Coding Advantage + +Rownd is uniquely positioned for the AI-driven development era: + +- Clean, consistent API patterns that AI tools can easily understand +- Well-documented interfaces with predictable behaviors +- Dashboard-configurable options reducing custom code requirements +- Separation of authentication logic from application code +- Simplified state management reducing cognitive complexity + +For teams using VIBE coding (AI prompt-based development), Rownd dramatically reduces the complexity AI needs to manage, while Cognito's configuration-heavy approach is difficult to express through prompts and requires deep AWS expertise. + +### 7. No-Code Customization & Administration + +Rownd empowers non-technical teams with: + +- Visual authentication designer for rapid iteration +- Self-service user management reducing support overhead +- [Dynamic group management](/configuration/user-accounts/groups) for flexible access control +- No-code branding and customization options +- Self-service email template management + +Cognito requires developer involvement for nearly all customizations, creating bottlenecks and slowing iteration cycles. + +### 8. Predictable Pricing Without Hidden Costs + +Rownd provides straightforward pricing: + +- Clear per-user pricing model +- No additional charges for infrastructure +- No surprising Lambda invocation costs +- No data transfer or storage fees +- No separate charges for additional features + +Cognito's pricing can become complex and unpredictable when factoring in associated AWS services like Lambda, API Gateway, CloudFront, and other infrastructure required for a complete authentication solution. + +## When to Choose Rownd + +Rownd is particularly well-suited for: + +1. **Teams without deep AWS expertise** who need authentication that works without spending weeks configuring it +2. **AI-driven development teams** using VIBE coding who need a platform that works seamlessly with AI assistants +3. **Mobile-first companies** requiring comprehensive native mobile libraries that work out of the box +4. **Startups and growth-stage companies** needing to move quickly without security compromises +5. **Product-led growth initiatives** leveraging [progressive profiling](/configuration/user-accounts/progressive-profiles) and [smart links](/magic-links/overview) +6. **Applications requiring customized authentication flows** without Lambda triggers and complex backends +7. **Enterprise organizations** needing immediate compliance and security certifications with a dedicated auth provider +8. **Teams with limited engineering resources** who can't dedicate developers to maintaining authentication infrastructure +9. **Organizations seeking to reduce AWS bill complexity** with predictable authentication pricing + +## Summary + +While Amazon Cognito offers powerful capabilities as part of the AWS ecosystem, it comes with significant complexity, configuration requirements, and development overhead. Rownd delivers a comprehensive, fully-managed authentication platform that works immediately with minimal setup while providing enterprise-grade security. + +For enterprises seeking secure authentication without engineering bottlenecks, and for VIBE coders looking for clean, consistent patterns that work well with AI-assisted development, Rownd provides a dramatically faster path to production with superior user experiences and growth-oriented features that Cognito simply doesn't offer without extensive custom development. \ No newline at end of file diff --git a/rownd-docusaurus/docs/welcome/comparisons/firebase.mdx b/rownd-docusaurus/docs/welcome/comparisons/firebase.mdx new file mode 100644 index 0000000..e559a7e --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/firebase.mdx @@ -0,0 +1,148 @@ +--- +title: "Rownd vs Firebase" +sidebarTitle: "Firebase" +--- + +# Rownd vs Firebase + +When evaluating authentication and user management solutions, understanding the key differences between specialized platforms and general-purpose tools is essential. This comparison highlights how Rownd's purpose-built user management platform offers unique advantages over Firebase Authentication, particularly for teams requiring dynamic control, cross-platform consistency, and authentication innovation. + +## Modern Authentication vs. Legacy Approach + +Firebase offers a broad development platform with authentication as just one of its many components. While functional for basic needs, Firebase Authentication hasn't seen significant innovation in years and shows an over-focus on Google's ecosystem. + +Rownd, in contrast, is a specialized user management platform built for modern development practices: + +**🔄 100% Dynamic User Management** - Rownd's platform lets you modify nearly every aspect of your user management flows without code changes or redeployments. With 95% of customizations available directly from the dashboard, product teams can test, iterate, and optimize the entire user experience in real-time rather than waiting for engineering resources. + +**📱 Truly Cross-Platform** - Unlike Firebase's web-first approach with mobile as an afterthought, Rownd provides complete feature parity across platforms with native SDKs for iOS, Android, React Native, Flutter, and Expo. This unified architecture ensures users enjoy a consistent, native-feeling experience across all their devices. + +**🤖 AI-Ready & VIBE Optimized** - Rownd is designed from the ground up to work seamlessly with AI tools and VIBE (Visual Integrated Development Experiences) workflows. With well-documented patterns, consistent APIs, and dashboard-configurable options, Rownd dramatically reduces the complexity AI assistants need to navigate, enabling 50-70% faster implementation with minimal security risks. + +## Feature Comparison + +| Feature | Rownd | Firebase | Rownd Advantage | +|---------|-------|----------|-----------------| +| **[Dynamic Authentication](/configuration/customizations/global-style)** | Instant, no-code customization | Custom implementation required | Rownd lets you tweak authentication logic and UI in real time without touching code | +| **[No-Code Administration](/configuration/applications)** | Visual authentication builder | Cloud Functions required | Rownd empowers non-developers to build and iterate user journeys without developer intervention | +| **[Smart Links](/magic-links/overview)** | Flexible deep linking | Limited campaign targeting | Rownd's Smart Links drive unified auth flow across web and apps without additional landing pages | +| **[Agent-Centric](/configuration/applications)** | AI-first with Admin SDK | Admin SDK requires setup | Rownd's platform is designed for autonomous agent governance and rapid automation | +| **[Multi-Platform](/sdk-reference/overview)** | 12+ SDKs for Web3 | Limited frameworks | Rownd extends authentication to blockchain onboarding and more backend frameworks | +| **[UI & Design](/configuration/customizations/global-style)** | Global style, hosted pages | Dashboard centralized | Rownd centralizes design controls in the dashboard without requiring HTML/CSS expertise | +| **[Group Management](/configuration/user-accounts/groups)** | Dynamic rules with web hooks | Custom cloud functions | Rownd's dynamic group rules simplify access control and reduce custom code | +| **[Integration Network](/configuration/integrations/overview)** | Extensible, pre-built connectors | Tight Firebase coupling | Rownd's catalog of pre-built connectors accelerate syncs without developer work | +| **[Login Methods](/configuration/authentication-methods/overview)** | OIDC, login links, Email/pass, OAuth | Standard methods | Rownd adds specialized government/military identity providers plug-and-play | +| **[User Management](/configuration/user-accounts/overview)** | Instant Use Console integration | Basic profile support | Rownd preserves context from anonymous to authenticated seamlessly | +| **[UI Out-of-the-box](/configuration/customizations/global-style)** | Prebuilt, customizable UI | Basic Firebase UI kit | Rownd's no-code theming applies uniformly across SDKs | +| **[Profile Management](/configuration/user-accounts/user-profiles)** | Custom fields, conditional profiles | Basic profile | Rownd offers native custom fields and conditional logic without external storage | +| **[Session Management](/api-reference/user-sessions/app/revoke-user-sessions)** | Real-time token handling | Basic refresh | Rownd's built-in dashboard analytics and revocation rules are more accessible | +| **[Custom Domains](/configuration/customizations/global-style)** | First-party domain support | Firebase domain only | Rownd supports custom domains and applies custom domains directly to auth endpoints | +| **[OIDC Provider](/configuration/oidc/overview)** | Full OpenID Connect provider | Auth provider only | Rownd includes OIDC provider in core platform; Firebase requires upgrade | +| **[APIs & SDKs](/api-reference/authentication/overview)** | REST APIs, WebSockets, comprehensive SDKs | Extensive APIs | Rownd adds pre-built no-code connectors | +| **[Security Rules](/configuration/user-accounts/groups)** | Dynamic group rules | Firebase Security Rules | Rownd's dynamic groups replace manual rules wiring in security rules | + +## Key Advantages of Rownd Over Firebase + +### 1. Dynamic Authentication vs. Static Implementation + +Rownd's no-code dashboard enables real-time flow changes: + +- Make authentication changes without code deployments +- Test different sign-in methods instantly +- Modify UI components without CSS/HTML knowledge +- Implement A/B tests on authentication flows +- Update branding, text, and behavior in seconds + +Firebase requires SDK or UI code updates, rebuilds, and redeployments for almost any authentication customization, slowing iteration cycles and requiring developer resources for even minor tweaks. + +### 2. Platform Neutrality vs. Google-Centric + +Rownd provides a truly platform-agnostic approach: + +- Equal support for all identity providers (Apple, Google, etc.) +- Consistent implementation across all platforms +- No preference for particular ecosystems +- Balanced feature development across authentication methods +- Native-feeling experiences on every platform + +Firebase, being a Google product, naturally favors Google authentication. This creates inconsistencies in implementation quality and user experience, particularly evident in Firebase's weaker Apple Sign-In support compared to its Google Sign-In implementation. + +### 3. Authentication Innovation vs. Maintenance Mode + +Rownd continuously introduces modern authentication capabilities: + +- [Instant Users](/configuration/authentication-methods/instant-users) for zero-friction onboarding +- [Progressive profiling](/configuration/user-accounts/progressive-profiles) for staged data collection +- [Smart Links](/magic-links/overview) for cross-platform deep linking +- [Dynamic user groups](/configuration/user-accounts/groups) for automated access control +- Contextual authentication based on user behavior + +Firebase Authentication has remained largely unchanged for years, with minimal innovation beyond basic maintenance and compliance updates. While stable, it lacks modern authentication patterns that increase conversion and enhance user experience. + +### 4. Authentication Specialization vs. General Purpose + +Rownd focuses exclusively on authentication excellence: + +- Purpose-built for comprehensive user management +- Specialized expertise in authentication security +- Continuous innovation in conversion optimization +- Advanced authentication workflows without custom code +- Enterprise-grade security as a core competency + +Firebase divides development resources across its entire platform (database, hosting, machine learning, etc.), leaving authentication as just one feature among many rather than a specialized focus area. + +### 5. No-Code Customization vs. Developer-Required + +Rownd empowers non-technical teams: + +- Visual authentication flow designer +- Dashboard-based user management +- Self-service branding and customization +- Real-time method additions and modifications +- Template-based email customization + +Firebase requires developer intervention for almost all authentication customizations, creating bottlenecks and preventing marketing and product teams from optimizing user journeys independently. + +### 6. True Mobile-First vs. Web-Adapted Experience + +Rownd was built from the ground up with mobile experiences in mind: + +- Native mobile libraries with platform-specific optimizations +- Deep integration with biometric authentication +- Unified authentication across all touch points +- Responsive components automatically adapting to any screen size +- Complete feature parity between web and mobile implementations + +Firebase's mobile SDKs often feel like adaptations of their web-first approach, requiring more custom development to provide truly native-feeling mobile experiences. + +### 7. AI & VIBE Development Friendly vs. Legacy Patterns + +Rownd is uniquely positioned for the AI-driven development era: + +- Clean, consistent API patterns easily understood by AI tools +- Well-documented interfaces with predictable behaviors +- Dashboard-configurable options reducing custom code requirements +- Separation of authentication logic from application code +- Implementation patterns that work reliably with AI assistants + +Firebase's complex, configuration-heavy approach with custom Security Rules and intertwined authentication/database logic is more difficult for AI tools to navigate and implement correctly. + +## When to Choose Rownd (vs. Firebase) + +Rownd is particularly well-suited for: + +1. **Teams seeking authentication innovation** beyond basic email/password and social login +2. **Mobile-first companies** requiring comprehensive native mobile libraries +3. **Marketing and product teams** who need control over user journeys without developer intervention +4. **Organizations requiring rapid iteration** of authentication flows and user experiences +5. **Companies with cross-platform products** needing consistent authentication experiences +6. **Teams using AI-assisted development** who need platforms optimized for VIBE workflows +7. **Startups and enterprises** requiring more sophisticated user management than Firebase offers + +## Summary + +While Firebase provides a functional authentication system as part of its broader development platform, it lacks the innovation, specialization, and dynamic capabilities that Rownd delivers. Firebase's approach to authentication hasn't evolved significantly in years, while Rownd continues to push the boundaries of what's possible in user management. + +Rownd enhances Firebase-like functionality with no-code dynamic controls, Smart Links, and agent-centric APIs, tailored for high-security and fast iteration teams. Its specialized focus on authentication excellence delivers superior user experiences, higher conversion rates, and more flexible implementation options across all platforms. + +For teams seeking modern, dynamic user management that adapts to their needs without constant development overhead, Rownd represents a significant upgrade over Firebase's static authentication approach. \ No newline at end of file diff --git a/rownd-docusaurus/docs/welcome/comparisons/overview.mdx b/rownd-docusaurus/docs/welcome/comparisons/overview.mdx new file mode 100644 index 0000000..e238a43 --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/overview.mdx @@ -0,0 +1,106 @@ +--- +title: "Choosing the Right User Management Platform" +sidebarTitle: "Overview" +--- +Selecting the right user management platform is a critical decision that impacts everything from security and compliance to user experience and development agility. The right solution can accelerate development, increase conversion rates, and provide enterprise-grade security while reducing engineering overhead. + +## Why Rownd Stands Apart + +Rownd represents a fundamental shift in how user management is implemented and maintained. Unlike legacy authentication providers that have gradually expanded their offerings, Rownd was built from the ground up as a complete user management platform for modern development practices. + +### 🔄 100% Dynamic User Management + +Rownd's platform lets you modify nearly every aspect of your user management flows without code changes or redeployments: + +- Real-time authentication flow updates without engineering involvement +- 95% of customizations available directly from the dashboard +- Instant method additions, branding changes, and flow modifications +- Dynamic rule-based user groups for automated access control +- Contextual authentication that adapts to user behavior and location + +This dynamic architecture empowers product and marketing teams to test, iterate, and optimize the entire user experience without waiting for development resources. + +### 🤖 AI Development Ready & VIBE Optimized + +Rownd is specifically engineered for AI-assisted development: + +- Clean, consistent API patterns easily understood by AI tools +- Well-documented interfaces with predictable behaviors +- Dashboard-configurable options reducing custom code requirements +- Separation of authentication logic from application code +- Implementation patterns that work reliably with AI assistants + +For teams using Visual Integrated Development Experiences (VIBE) with AI coding assistants, Rownd dramatically reduces the complexity AI needs to navigate, enabling 50-70% faster implementation with minimal security risks. + +### 🛡️ Enterprise-Proven, Military-Grade Security + +Rownd delivers enterprise-level security without enterprise-level complexity: + +- [SOC 2 Type II certified](/security/SOC2-type2) +- [HIPAA-ready](/security/hipaa-ready) data handling +- GovCloud approved architecture +- Military-grade encryption at rest and in transit +- Government identity provider integrations (Login.gov, AF Mobile Connect) +- Advanced security controls with minimal configuration + +Organizations including government agencies, healthcare providers, and financial institutions trust Rownd's security architecture for their most sensitive identity management needs. + +### 🚀 Implementation in Hours, Not Weeks + +Rownd dramatically reduces time-to-market: + +- Drop-in SDKs for 12+ platforms that work immediately +- No backend configuration or specialized expertise required +- Zero server-side setup to maintain +- Pre-built customizable components for all platforms +- Dashboard configuration reducing code requirements by 60-80% + +While legacy solutions require extensive configuration, custom rules, and redirect URI management, Rownd works out of the box with sensible defaults that can be tailored through a user-friendly dashboard. + +### 📱 True Mobile-First Architecture + +Rownd provides a genuinely mobile-optimized experience: + +- Native libraries with platform-specific optimizations +- Complete feature parity between web and mobile +- Deep integration with native platform capabilities +- Unified authentication across all user touchpoints +- Smart Links for seamless cross-platform navigation + +This unified approach ensures users enjoy consistent, native-feeling experiences regardless of how they interact with your products. + +## Head-to-Head Comparisons + +See how Rownd compares to leading alternatives across key dimensions: + +### [Rownd vs Auth0](./auth0) + +Auth0 is a well-established authentication service that many organizations have used for years. However, its aging architecture, redirect-based flows, and limited user management capabilities place it at a significant disadvantage compared to Rownd's modern platform. [Learn how Rownd outperforms Auth0 →](./auth0) + +### [Rownd vs Clerk](./clerk) + +Clerk offers authentication with some user management features but lacks the comprehensive capabilities and flexibility of Rownd's platform. [Discover why Rownd provides superior value over Clerk →](./clerk) + +### [Rownd vs Cognito](./cognito) + +Amazon Cognito provides authentication for AWS applications but requires significant AWS knowledge and lacks the dynamic capabilities and ease of use that Rownd delivers. [See how Rownd simplifies what Cognito complicates →](./cognito) + +### [Rownd vs Firebase](./firebase) + +Google's Firebase offers authentication as part of its development platform, but its limited customization, complex implementation, and web-first approach can't match Rownd's flexibility and native mobile support. [Explore Rownd's advantages over Firebase →](./firebase) + +### [Rownd vs Supabase](./supabase) + +Supabase Auth provides basic authentication capabilities within its broader platform, but falls short of Rownd's comprehensive user management features and enterprise-ready security. [Compare Rownd's full platform to Supabase →](./supabase) + +### [Rownd vs Zitadel](./zitadel) + +Zitadel offers an open-source identity solution with some enterprise features, but requires significant configuration and lacks the dynamic, no-code capabilities that make Rownd so powerful. [See why Rownd outperforms Zitadel →](./zitadel) + +## The Bottom Line + +Choosing a user management platform is about more than just authentication—it's about enabling growth, optimizing user experiences, and freeing your team to focus on your core product. + +Rownd delivers a complete user management platform that works out of the box, with the flexibility to adapt to your evolving needs without constant development overhead. Whether you're building a new product, scaling an existing one, or modernizing your user management infrastructure, Rownd provides the most comprehensive solution with the lowest implementation and maintenance burden. + +Experience the difference that a purpose-built, modern user management platform can make for your organization. [Get started with Rownd today →](https://rownd.io) \ No newline at end of file diff --git a/rownd-docusaurus/docs/welcome/comparisons/supabase.mdx b/rownd-docusaurus/docs/welcome/comparisons/supabase.mdx new file mode 100644 index 0000000..bd8eda9 --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/supabase.mdx @@ -0,0 +1,144 @@ +--- +title: "Rownd vs Supabase" +sidebarTitle: "Supabase" +--- + +# Rownd vs Supabase + +When evaluating tools for your application stack, it's important to understand how different solutions address specific needs. This comparison highlights how Rownd's specialized user management platform can complement Supabase's excellent database capabilities, creating a powerful combination for modern applications. + +## Complementary Solutions for Modern Applications + +Supabase has emerged as a popular open-source Firebase alternative, offering excellent database capabilities, real-time subscriptions, storage, and basic authentication. However, while Supabase excels as a database and backend-as-a-service, its authentication capabilities are relatively basic—more of a placeholder than a comprehensive solution. + +Rownd, on the other hand, is purpose-built as a complete user management platform with enterprise-grade security, no-code customization, and advanced user lifecycle features. This creates an ideal opportunity: **use Rownd for comprehensive user management and Supabase for everything else**. + +This combination gives you: +- Best-in-class user management, authentication, and progressive profiling with Rownd +- Powerful database capabilities, real-time features, and storage with Supabase +- A complete, modern application stack without compromises + +## Rownd: Complete User Management for Modern Development + +Rownd stands apart as a specialized user management platform specifically engineered for today's development landscape: + +**🤖 AI-Ready & VIBE Optimized** - Rownd is designed from the ground up to work seamlessly with AI tools and VIBE (Visual Integrated Development Experiences) workflows. With well-documented patterns, consistent APIs, and dashboard-configurable options, Rownd dramatically reduces the complexity AI assistants need to navigate, enabling 50-70% faster implementation with minimal security risks. + +**📱 Truly Mobile-First** - Unlike solutions that prioritize web then add mobile support, Rownd provides complete feature parity across platforms with native SDKs for iOS, Android, React Native, Flutter, and Expo alongside optimized web experiences. This unified architecture ensures users enjoy a consistent, native-feeling experience across all their devices. + +**🔄 100% Dynamic User Management** - Rownd's platform lets you modify nearly every aspect of your user management flows without code changes or redeployments. With 95% of customizations available directly from the dashboard, product teams can test, iterate, and optimize the entire user experience in real-time rather than waiting for engineering resources. + +## Feature Comparison + +| Feature | Rownd | Supabase Auth | Rownd Advantage | +|---------|-------|--------------|-----------------| +| **Core Focus** | Complete user management platform | Database with basic authentication | Rownd focuses exclusively on user management excellence, while Supabase spreads resources across multiple features | +| **[Authentication Methods](/configuration/authentication-methods/overview)** | Modern, password-less: [email links](/configuration/authentication-methods/email), [SMS OTP](/configuration/authentication-methods/phone-sms), social login, [passkeys](/configuration/authentication-methods/passkeys), [guest users](/configuration/authentication-methods/guests), [instant users](/configuration/authentication-methods/instant-users) | Email/password, magic links, OAuth providers, phone auth via Twilio | Rownd provides more authentication options with zero-friction options like Instant Users and superior implementation of passwordless methods | +| **[Mobile Support](/sdk-reference/mobile/overview)** | Complete native SDKs for [iOS](/sdk-reference/mobile/ios), [Android](/sdk-reference/mobile/android), [React Native](/sdk-reference/mobile/react-native), [Flutter](/sdk-reference/mobile/flutter), and [Expo](/sdk-reference/mobile/expo) | Limited mobile support, requires significant custom code for native-feeling experiences | Rownd's mobile-first architecture provides platform-specific optimizations and complete feature parity across devices | +| **[In-Context Authentication](/configuration/customizations/global-style)** | Seamless in-app authentication without redirects or page refreshes | Authentication often requires page refreshes or redirection | Rownd's in-context authentication maintains user flow and increases conversion rates by 30-40% | +| **[Progressive Profiling](/configuration/user-accounts/progressive-profiles)** | Built-in support for incremental data collection based on user journey stage | No native progressive profiling support | Rownd enables gradual user data collection that increases profile completion rates by 50-75% | +| **[Dynamic User Groups](/configuration/user-accounts/groups)** | Automated, rule-based user grouping with access control | Basic role-based access control | Rownd's dynamic groups automatically assign users based on behavior, attributes, or custom rules | +| **[Smart Links](/magic-links/overview)** | Universal deep linking system across platforms | Basic email magic links for authentication only | Rownd's Smart Links drive users to specific actions across platforms while maintaining context | +| **[No-Code Customization](/configuration/customizations/global-style)** | Visual dashboard for authentication flows, branding, and user management | Requires code changes for most customizations | Rownd empowers non-technical teams to optimize user flows without developer involvement | +| **[User Data Management](/configuration/user-accounts/user-profiles)** | Comprehensive user profile management, progressive data collection | Basic user metadata storage | Rownd provides sophisticated user data collection, storage, and management capabilities | +| **[Enterprise Security](/security/overview)** | [SOC 2 Type II certified](/security/SOC2-type2), [HIPAA-ready](/security/hipaa-ready), military-grade encryption | Limited compliance certifications, basic security controls | Rownd delivers enterprise-grade security with minimal configuration | +| **[Integration with Supabase](/configuration/integrations/overview)** | Can work alongside Supabase for best-of-breed stack | N/A | Rownd complements Supabase's strengths while addressing its authentication limitations | + +## Key Advantages of Rownd Over Supabase Auth + +### 1. Specialized Focus vs. General-Purpose + +Rownd is purpose-built for user management: + +- Dedicated product focus on authentication and user management +- Specialized expertise in security, compliance, and user experience +- Continuous innovation in conversion optimization and user lifecycle +- Comprehensive features addressing the entire authentication journey +- Enterprise-grade security as a core competency + +While Supabase spreads its development resources across database, storage, real-time features, and more, Rownd concentrates exclusively on user management excellence. + +### 2. Complete Mobile Experience vs. Limited Support + +Rownd delivers a truly mobile-optimized experience: + +- Native SDKs built specifically for each platform +- Biometric authentication deeply integrated with native capabilities +- Consistent features and behavior across all platforms +- Optimized mobile-specific authentication flows +- Deep linking and universal navigation patterns + +Supabase's authentication is primarily web-focused, with limited mobile SDKs that require significant custom development to provide a native-feeling experience. + +### 3. Dynamic No-Code Platform vs. Code-Required Changes + +Rownd empowers non-technical teams: + +- Visual authentication designer for rapid iteration +- Dashboard-based user management without code changes +- Real-time flow modifications without redeployment +- Self-service customization options for marketing and product teams +- Instant method additions and branding changes + +Supabase requires developer involvement for almost all authentication customizations, creating bottlenecks and slowing iteration cycles. + +### 4. Growth-Optimized Features vs. Basic Authentication + +Rownd includes powerful growth acceleration capabilities: + +- [Instant Users](/configuration/authentication-methods/instant-users) for immediate product exploration +- [Progressive profiling](/configuration/user-accounts/progressive-profiles) for incremental data collection +- [Smart Links](/magic-links/overview) for cross-platform deep linking +- Contextual authentication based on user behavior +- Optimized conversion funnels with real-time analytics + +Supabase offers basic authentication functionality without the growth-oriented features that modern product-led companies need to optimize acquisition and conversion. + +### 5. Enterprise-Ready Security vs. Basic Controls + +Rownd delivers enterprise-level security: + +- [SOC 2 Type II certified](/security/SOC2-type2) infrastructure +- [HIPAA-ready](/security/hipaa-ready) data handling +- Advanced authentication security with minimal configuration +- Military-grade encryption at rest and in transit +- Government and financial institution security compliance + +Supabase offers basic security controls but lacks the comprehensive compliance certifications and advanced security features that enterprises require. + +## The Best of Both Worlds: Rownd + Supabase + +Instead of viewing this as an either/or decision, consider how these tools complement each other: + +### How to Integrate Rownd with Supabase + +1. **User Authentication & Management**: Use Rownd for all user authentication, profile management, and access control +2. **Database & Backend Services**: Use Supabase for database, storage, and real-time features +3. **Identity Sharing**: Pass Rownd JWT tokens to Supabase for secure session management +4. **Access Control**: Use Rownd groups to manage permissions that Supabase respects + +This integration gives you: +- Best-in-class user management with Rownd +- Excellent database and backend services with Supabase +- A seamless experience for both users and developers +- The strongest aspects of both platforms without compromise + +## When to Choose Rownd (vs. Supabase Auth) + +Rownd is the better authentication choice when: + +1. **Mobile is a first-class citizen** in your application strategy +2. **Growth and conversion optimization** are primary concerns +3. **Non-technical teams** need control over user journeys +4. **Enterprise security and compliance** are requirements +5. **User experience consistency** across platforms is critical +6. **AI-driven development** is part of your workflow +7. **Time-to-market** is a competitive advantage + +## Summary + +While Supabase excels as a database and backend-as-a-service platform, its authentication capabilities are more of a starting point than a comprehensive solution. Rownd addresses this gap with a purpose-built user management platform that complements Supabase's strengths. + +The ideal modern stack combines Rownd's specialized user management with Supabase's excellent database capabilities. This combination provides a complete, best-of-breed solution that delivers superior results across the entire application lifecycle. + +By using Rownd for authentication and user management alongside Supabase for everything else, you get the best of both worlds: specialized excellence in each critical area rather than compromising with general-purpose tools that don't excel in any single domain. \ No newline at end of file diff --git a/rownd-docusaurus/docs/welcome/comparisons/zitadel.mdx b/rownd-docusaurus/docs/welcome/comparisons/zitadel.mdx new file mode 100644 index 0000000..9939cfe --- /dev/null +++ b/rownd-docusaurus/docs/welcome/comparisons/zitadel.mdx @@ -0,0 +1,164 @@ +--- +title: "Rownd vs Zitadel" +sidebarTitle: "Zitadel" +--- +When evaluating comprehensive user management platforms for your application, understanding the key differences between options is essential. This comparison highlights how Rownd's complete user management platform offers unique advantages over Zitadel's open-source offering, particularly for teams requiring full user lifecycle management, no-code customization, and enterprise-grade security without complex infrastructure. + +## Rownd: Complete User Management for Modern Development + +Rownd stands apart as a complete user management platform specifically engineered for today's development landscape: + +**🤖 AI-Ready & VIBE Optimized** - Rownd is designed from the ground up to work seamlessly with AI tools and VIBE (Visual Integrated Development Experiences) workflows. With well-documented patterns, consistent APIs, and dashboard-configurable options, Rownd dramatically reduces the complexity AI assistants need to navigate, enabling 50-70% faster implementation with minimal security risks. + +**📱 Truly Mobile-First** - Unlike solutions that prioritize web then add mobile support, Rownd provides complete feature parity across platforms with native SDKs for iOS, Android, React Native, Flutter, and Expo alongside optimized web experiences. This unified architecture ensures users enjoy a consistent, native-feeling experience across all their devices. + +**🔄 100% Dynamic User Management** - Rownd's platform lets you modify nearly every aspect of your user management flows without code changes or redeployments. With 95% of customizations available directly from the dashboard, product teams can test, iterate, and optimize the entire user experience in real-time rather than waiting for engineering resources. + +## Feature Comparison + +| Feature | Rownd | Zitadel (Self-hosted) | Rownd Advantage | +|---------|-------|-------|-----------------| +| **[Security & Compliance](/security/overview)** | [SOC 2 Type II certified](/security/SOC2-type2), [HIPAA-ready](/security/hipaa-ready), GovCloud approved, military-grade security controls | Requires own attestation, not DoD approved, requires ATO | Rownd's compliance certifications provide immediate compliance readiness and enable deployment in regulated environments without additional security reviews | +| **[Authentication Methods](/configuration/authentication-methods/overview)** | Modern, password-less: [email links](/configuration/authentication-methods/email), [SMS OTP](/configuration/authentication-methods/phone-sms), social login, [passkeys](/configuration/authentication-methods/passkeys), [guest users](/configuration/authentication-methods/guests), [instant users](/configuration/authentication-methods/instant-users) | Traditional email/password, limited SMS, OIDC providers | Rownd's password-less approach eliminates password-related security risks and reduces support tickets by 70-80% while enabling zero-friction initial engagement | +| **[In-Context Authentication](/configuration/customizations/global-style)** | Seamless in-app/in-context authentication maintains user flow without disruptive redirects | Redirect to separate auth page | Keeping users in context during authentication increases conversion rates by 30-40% and reduces bounce rates | +| **[User Management](/configuration/user-accounts/overview)** | [Instant Users](/configuration/authentication-methods/instant-users) assign a unique Rownd ID to every visitor, unified account across methods, self-service profiles | Basic user management requiring implementation | Rownd preserves user context from first visit and enables progressive profiling, increasing signup completion by 50-75% | +| **[Universal Link Support](/magic-links/overview)** | Full [smart links](/magic-links/overview) implementation with deep linking across platforms | Limited, requires custom implementation | Smart Links let you drive users into any step of your flow across web and apps, maintaining context through authentication flows | +| **[Social & Government Authentication](/configuration/authentication-methods/overview)** | Native one-click support for [Google](/configuration/authentication-methods/google), [Apple](/configuration/authentication-methods/apple), Login.gov, AF Mobile Connect, and any OIDC provider | Requires custom OIDC implementation | Rownd's pre-configured providers can be set up in under a minute, with Google One-click increasing landing page conversion by 33% | +| **[Automations](/configuration/automations/overview)** | Time-based and page-based [automation triggers](/configuration/automations/overview), contextual authentication, device-based context | No automation capabilities | Rownd's contextual authentication triggers based on user behavior increase conversion rates by 25-35% | +| **[UI Components](/sdk-reference/overview)** | Ready-to-use, customizable [visual components](/configuration/customizations/global-style) across 12+ platforms – web, mobile, cross-platform | Basic redirect-based components, limited React components, no native mobile components | Rownd provides pre-built, customizable components for all platforms, accelerating development and maintaining UX consistency | +| **[Mobile-First Architecture](/sdk-reference/mobile/overview)** | Comprehensive native mobile libraries for [iOS](/sdk-reference/mobile/ios), [Android](/sdk-reference/mobile/android), [React Native](/sdk-reference/mobile/react-native), [Flutter](/sdk-reference/mobile/flutter), and [Expo](/sdk-reference/mobile/expo) with complete feature parity | OIDC implementation only, no native UI components | Rownd's mobile-first approach ensures seamless authentication experiences across all devices with 40-60% less development time | +| **[AI & VIBE Coding Support](/api-reference/authentication/overview)** | Well-documented APIs, consistent patterns easily described in prompts, dashboard-configurable options, clean separation between auth and app code | No specific AI-assisted capabilities, requires extensive custom code | Rownd is designed for VIBE (AI prompt-based) coding with clear patterns that reduce complexity for AI tools and minimize configuration errors | +| **[Growth Features](/configuration/user-accounts/progressive-profiles)** | [Smart links](/magic-links/overview), cross-app authentication, customizable auth flow location, [dynamic user groups](/configuration/user-accounts/groups), [progressive profiling](/configuration/user-accounts/progressive-profiles) | Limited magic links, basic group support | Rownd enables frictionless user acquisition and optimized authentication placement, improving signup completion by 20-30% | +| **[Platform Management](/configuration/applications)** | Full-featured dashboard, user profile self-management portal, no-code admin interface | Basic interface, requires implementation | Rownd's admin tools reduce support tickets by 40-60% and enable non-technical teams to resolve user issues without developer involvement | +| **[Customization](/configuration/customizations/global-style)** | Visual authentication designer, no-code sign-in method addition, dynamic branding rules, [sub-brand management](/configuration/customizations/sub-brands) | Requires development, basic HTML templates | Rownd allows non-technical teams to optimize authentication flows and maintain brand consistency, reducing time-to-market by weeks | +| **Implementation & Maintenance** | Fully managed SaaS, automatic updates, 24/7 support | Self-hosted requiring extensive infrastructure and maintenance | Rownd eliminates the need for dedicated infrastructure, security updates, and maintenance resources that self-hosted solutions require | +| **Total Cost** | Starting at $1,250/month | $7,040-$11,205/month TCO (with existing K8s) | Rownd's SaaS model eliminates hidden infrastructure and maintenance costs, providing significantly lower total cost of ownership | + +## Key Advantages of Rownd Over Zitadel + +### 1. Simplified Implementation & Zero Maintenance + +Rownd provides a fully managed authentication solution with: + +- Zero infrastructure to maintain or configure +- Automatic security updates and patches +- No need for dedicated database resources +- Elimination of monthly maintenance tasks +- 24/7 support with Slack-based assistance + +Unlike Zitadel's self-hosted approach which requires significant infrastructure resources, PostgreSQL databases, Kubernetes expertise, and monthly maintenance commitments, Rownd can be implemented in minutes with no ongoing maintenance burden. + +### 2. Enterprise-Ready Security & Compliance + +Rownd's platform comes with immediate compliance capabilities: + +- [SOC 2 Type II certification](/security/SOC2-type2) out of the box +- [HIPAA readiness](/security/hipaa-ready) for healthcare applications +- GovCloud approval for government deployments +- DoD-approved for military applications +- Robust security controls with continuous monitoring + +These pre-certified features enable immediate deployment in regulated environments without the extensive security reviews and attestations required for self-hosted Zitadel implementations. + +### 3. Superior User Experience + +Rownd's platform provides authentication experiences designed for modern user expectations: + +- In-context authentication without disruptive redirects +- [Instant Users](/configuration/authentication-methods/instant-users) for immediate product exploration +- Persistent authentication across sessions and devices +- Seamless mobile authentication with biometric options +- Contextual, adaptive authentication based on user behavior + +These features create a frictionless experience that increases conversion rates by 30-40% compared to Zitadel's more traditional redirect-based authentication model. + +### 4. Growth-Oriented Features + +Rownd includes built-in capabilities designed to accelerate user acquisition and engagement: + +- [Smart Links](/magic-links/overview) for targeted deep linking across platforms +- Time and page-based [automation triggers](/configuration/automations/overview) +- [Progressive profiling](/configuration/user-accounts/progressive-profiles) for incremental data collection +- Authentication that can be embedded anywhere (blogs, marketing pages) +- Cross-app authentication for unified user experiences + +These growth-focused features enable product-led strategies that can increase multi-product adoption by 25-35% compared to Zitadel's more basic implementation. + +### 5. True Mobile-First Architecture + +Rownd was built from the ground up with mobile experiences in mind: + +- Native mobile libraries with platform-specific optimizations +- Complete feature parity between web and mobile implementations +- Biometric authentication deeply integrated with native capabilities +- Responsive components automatically adapting to any screen size +- Deep linking and universal navigation patterns across platforms +- Push notification support for authentication events + +While Zitadel requires extensive custom work to implement mobile experiences, Rownd's mobile-first approach reduces implementation time by 40-60% while providing a superior user experience that feels native on every platform. + +### 6. AI & VIBE Coding Advantage + +Rownd is uniquely positioned for the AI-driven development era: + +- Clean, consistent API patterns that AI tools can easily understand +- Well-documented interfaces with predictable behaviors +- Dashboard-configurable options reducing custom code requirements +- Separation of authentication logic from application code +- Standardized implementation patterns across platforms +- Simplified state management reducing cognitive complexity + +For teams using VIBE coding (AI prompt-based development), Rownd dramatically reduces the complexity AI needs to manage, resulting in: + +- 50-70% faster implementation with AI assistance +- Lower risk of security misconfiguration +- Reduced need for specialized authentication expertise +- Easier maintenance and updates +- Future-proof architecture as AI tools evolve + +Enterprise teams and VIBE coders alike will appreciate how Rownd's consistent, well-structured approach aligns perfectly with modern AI-assisted development workflows. + +### 7. No-Code Customization & Administration + +Rownd empowers non-technical teams with: + +- Visual authentication designer for rapid iteration +- Self-service user management reducing support overhead +- [Dynamic group management](/configuration/user-accounts/groups) for flexible access control +- No-code branding and customization options +- Self-service email template management + +This approach reduces dependency on development resources and allows product teams to iterate quickly without engineering bottlenecks—something impossible with Zitadel's development-focused approach. + +### 8. Dramatic Cost Advantage + +While Zitadel's open-source nature may appear free at first glance, the true Total Cost of Ownership reveals a different story: + +- Infrastructure costs: $340-$705/month (with existing K8s) +- Operational staff requirements: $6,000-$9,000/month +- Tools and monitoring: $200-$500/month +- Emergency fund for incidents: $500-$1,000/month +- **Total monthly TCO: $7,040-$11,205** (with existing infrastructure) + +Rownd's SaaS pricing starts at $1,250/month, providing a fully managed solution at a fraction of Zitadel's self-hosted TCO, while eliminating the complexity, maintenance burden, and hidden costs. + +## When to Choose Rownd + +Rownd is particularly well-suited for: + +1. **AI-driven development teams** using VIBE coding who need a platform that works seamlessly with AI assistants +2. **Mobile-first companies** requiring comprehensive native mobile libraries that work out of the box +3. **Enterprise organizations** needing immediate compliance and security certifications without lengthy attestation processes +4. **Teams lacking dedicated DevOps/security resources** who can't allocate 80-120 hours monthly to authentication maintenance +5. **Growth-focused organizations** needing authentication that enhances rather than hinders conversion +6. **Regulated industries** requiring immediate [compliance certifications](/security/overview) +7. **Organizations with limited engineering resources** who need to empower product and marketing teams +8. **Companies without existing Kubernetes expertise** who don't want to manage complex infrastructure +9. **Military and government contractors** requiring specialized [security controls](/security/overview) +10. **Product-led growth initiatives** leveraging [progressive profiling](/configuration/user-accounts/progressive-profiles) and [smart links](/magic-links/overview) + +## Summary + +While Zitadel offers a self-hosted open-source option, Rownd delivers a comprehensive, fully-managed platform with unique features that eliminate infrastructure overhead and empower non-technical teams. With its zero-maintenance approach, military-grade security, mobile-first architecture, and AI-friendly design, Rownd provides a superior authentication solution at a dramatically lower total cost of ownership. + +The true cost comparison is stark: Rownd's all-inclusive pricing starts at $1,250/month, while Zitadel's self-hosted solution requires $7,000-$11,000/month in infrastructure and operational expenses. For enterprises focused on innovation rather than infrastructure maintenance, and for VIBE coders seeking clean, consistent patterns to work with, Rownd represents the clear choice for modern authentication needs. diff --git a/rownd-docusaurus/docs/welcome/getting-started.mdx b/rownd-docusaurus/docs/welcome/getting-started.mdx new file mode 100644 index 0000000..433cb84 --- /dev/null +++ b/rownd-docusaurus/docs/welcome/getting-started.mdx @@ -0,0 +1,72 @@ +--- +title: "Getting started" +--- + +Welcome to Rownd - the AI-enabled Application Services Platform that powers your app's core services from sign-in to scale. We handle authentication, payments, user management, smart links, and more, so you can focus on building your product. + +## 1. Sign up for the Rownd platform +The Rownd platform is your command center for managing all your app's essential services. Configure authentication flows, set up payments, manage users, create smart links, and monitor everything from one unified dashboard. + +Open https://app.rownd.io to get started. Sign in with Google or email, and we'll create your first app instantly - **free for up to 1 million users**. + +## 2. Add your team +Building successful apps requires collaboration across domains. [Add your teammates](/administration/teams): developers, product managers, designers, and growth teams. Everyone can contribute without waiting for engineering cycles - from customizing sign-in flows to launching payment features. + +## 3. Get your app key +[Create](/configuration/app-credentials) your app key and secret to connect your application to Rownd's services. + +## 4. Install Rownd +With [over 15 SDKs](/sdk-reference/overview), Rownd integrates seamlessly into any stack: +- **Web Apps**: React, Vue, Angular, Next.js, and more +- **Mobile Apps**: iOS, Android, React Native, Flutter +- **Static Sites**: Netlify, Vercel, WordPress +- **Backend**: Node.js, Python, Ruby, Go, and others + +## 5. Enable powerful app services +Rownd goes beyond authentication to provide everything modern apps need: + +### 🔐 Authentication & User Management +- Passwordless sign-in with passkeys and magic links +- Social logins (Google, Apple, Meta) +- Built-in user profiles and management +- Cross-domain and cross-app authentication + +### 💳 Payments (Powered by Stripe) +- Start accepting payments in minutes +- Automatic Stripe Express account setup +- Built-in subscription management +- Just 1% platform fee - we cover all Stripe fees + +### 🔗 Smart Links & Deep Linking +- Universal links that work across web and mobile +- Built-in analytics and tracking +- Perfect for marketing campaigns and user onboarding +- Custom domains for branded experiences + +### 📧 Verification Services +- Email and phone verification +- Custom messaging and branding +- Built-in retry logic and deliverability optimization + +### 🤖 AI-Powered Features +- Intelligent user flow optimization +- Automated A/B testing for sign-in methods +- Predictive analytics for user behavior +- Smart routing based on user context + +## 6. Customize everything from the platform +One of Rownd's most powerful features is server-side control. Make instant changes without redeploying: +- Update authentication methods +- Modify UI components and branding +- Launch new payment products +- Create marketing campaigns with smart links +- All changes take effect immediately across all your apps + +## Get help +The Rownd team is here to support your success! Reach out to support@rownd.io for: +- Implementation guidance +- Best practices for your use case +- Custom enterprise features +- Migration assistance from other platforms + +**Start building with Rownd today - free up to 1 million users!** diff --git a/rownd-docusaurus/docs/welcome/overview.mdx b/rownd-docusaurus/docs/welcome/overview.mdx new file mode 100644 index 0000000..d34e51d --- /dev/null +++ b/rownd-docusaurus/docs/welcome/overview.mdx @@ -0,0 +1,208 @@ +--- +title: "Welcome to Rownd" +sidebarTitle: "Introduction" +--- +## Start building +### Choose your application type to get started + + + + App that runs on a device (Flutter, Swift, etc) + + + App that runs in a browser (React, Next.js, Vue, etc) + + + A hosted or custom website (Wordpress, Webflow, etc) + + + Server-based frameworks (Node.js, Django, etc) + + + + +Need to migrate from another authentication provider like Firebase, Auth0, or Cognito? [Take at look at our simple migration process!](/migration/overview) + +## Learn about Rownd + +Rownd is more than just authentication—it's Authentication+. While providing enterprise-grade authentication, Rownd delivers a complete platform that handles user management, engagement, and integration needs out of the box. Our platform combines security with simplicity, offering everything you need to create exceptional user experiences. + +### What makes Rownd Authentication+? + +- **Ready-to-use UI Components** + - Pre-built, customizable visual components across all SDKs + - Drop-in solutions that save months of development time + - Easy to customize and edit from the platform + +- **Complete User Management** + - Self-service user profiles + - Comprehensive admin dashboard + - Group management with instant invite links + - Advanced user segmentation and filtering + +- **Instant Users** + - **Immediate Recognition**: Every visitor gets a Rownd ID instantly + - **Progressive Enhancement**: The anonymous ID seamlessly transitions to a full user profile upon authentication + - **No Lost Data**: All user activity and data is preserved throughout the journey + - **Cookie-Free Tracking**: Replace messy cookies with secure, privacy-focused user identification + +- **Keep users in context: Cross-Domain, Cross-App, and Cross-Device Authentication** + - **Unified User Experience**: Users can sign up or sign in seamlessly across different platforms without needing to re-enter credentials. + - **Cross-Domain Authentication**: Securely authenticate users across multiple domains and applications, maintaining a consistent user session. + - **Reduced Friction**: Minimize barriers to entry, encouraging users to engage with your services wherever they are. + - **Magic Links**: Enable users to transition from web to mobile apps effortlessly with secure, one-click authentication. + - **Universal Links**: Provide a seamless experience by directing users to the appropriate app or web page based on their device. + +- **Simple Developer Experience** + - 15+ SDKs with industry-leading mobile support + - Built-in Google One-Tap integration + - OIDC Server for seamless SSO implementation + - Native Passkeys support + - No-code automations so Developers can focus on building + +- **No-Code Capabilities for the Growth, Product, and Design Teams** + - Self-service automation workflows - add sign-up, data collection, and more without writing code + - Visual customization tools - easily customize the look and feel of your product + - Component embedding without coding - add pre-built UI components to your product without writing code + - Built-in analytics dashboard - easily understand how users are interacting with your product + +- **Enterprise Integration** + - Deep integrations with Keycloak, Mailchimp, and more + - Flexible SMS provider options (BYO or use ours) + - Universal links for seamless experiences + - SOC 2 Type II certified and HIPAA ready + + + + + + + Get up and running in minutes. + + + Configure your authentication in the Rownd platform + + + Customize the look and feel of your sign-up prompts + + + Create self-service user-profile and manage user data + + + Add web-based NEAR wallets to your users in seconds. + + + + +## Sign-in methods + +Rownd supports a wide range of sign-in methods to cater to diverse user preferences and device capabilities. Some of the available methods include: + +- Sign in with Google +- Sign in with Apple +- Biometric authentication (via Passkeys) +- Email-based authentication with Rownd Sign-in Links +- SMS-based authentication with Rownd Sign-in Links + + +Explore our [sign-in methods](/configuration/authentication-methods/overview) documentation for a detailed look at each method and how to implement them. + +## Adaptive authentication + +Adaptive authentication is a powerful feature that tailors the authentication experience based on the user's device, providing the most convenient and secure authentication option. Rownd's adaptive sign-in detects the user's mobile device and adjusts the available authentication options accordingly. + +Learn more about [adaptive authentication](/configuration/authentication-methods/overview) and its benefits in our dedicated documentation. + + + +## User management + +Rownd's user management system enables you to easily manage and track user accounts while providing a seamless authentication experience. With Rownd, each user is associated with a unique identifier, allowing them to link multiple authentication methods to a single account. This prevents the creation of duplicate accounts and ensures a consistent user experience across various authentication methods. + +For more information on Rownd's user management capabilities and how it enhances the authentication process, see our [user management](/configuration/user-accounts/user-profiles) documentation. + + +## Security features + +Rownd's platform is designed with security in mind, offering features that help protect user accounts and sensitive data. Some of the security features include: + +- Strong encryption for data storage and transmission +- Passwordless technology +- Compliance with industry standards and regulations + +Read our [security features](./../security/overview) documentation for an in-depth look at Rownd's security measures. + + +## Increased sign-in rates + +By offering a diverse range of sign-in methods, adaptive authentication, and a seamless user experience, Rownd can significantly increase sign-in rates. A tailored authentication process can lead to higher user engagement and retention, as users are more likely to continue using an app that offers a smooth and convenient sign-in experience. + +Rownd is an innovative authentication platform designed to provide secure and user-friendly authentication methods for websites and mobile apps. By offering a variety of authentication options, such as email-based, SMS-based, and social sign-in methods, web3 wallet, and now passkeys. Rownd simplifies the user experience while maintaining strong security measures. + +One of the key benefits of using Rownd is its ability to significantly increase conversion rates. Traditional authentication methods often lead to user drop-off, with nearly half of app users abandoning the process due to complex or time-consuming sign-up steps. By streamlining the authentication process and offering multiple, convenient options, Rownd helps businesses minimize user drop-off and maximize conversion rates. This results in a larger, more engaged user base and greater overall success for your app. + + +Many website visitors get close to trying out your product, but are deterred by a sign up or registration process that asks for too much information (e.g., name, email address, password, etc). + +While social sign-in (e.g., Google or Facebook) is often seen as a solution to this problem, it can also be a deterrent to visitors that might not want their profile information transmitted to you before they trust your company. + +Rownd helps you build lasting relationships with your users without extra work on your part. + + + +## Instant Users: Every Visitor is a User + +Rownd revolutionizes user management with our "instant users" approach. Unlike traditional systems that only track authenticated users, Rownd assigns a unique identifier to every visitor from their first interaction. + +### How Instant Users Work + +- **Immediate Recognition**: Every visitor gets a Rownd ID instantly +- **Progressive Enhancement**: The anonymous ID seamlessly transitions to a full user profile upon authentication +- **No Lost Data**: All user activity and data is preserved throughout the journey +- **Cookie-Free Tracking**: Replace messy cookies with secure, privacy-focused user identification + + +With Rownd's instant users, you can start building relationships with visitors before they formally sign up. This means better analytics, more accurate user journeys, and no lost data when anonymous users convert to authenticated users. + + +### Benefits of Instant Users + +- **Better Analytics**: Track complete user journeys from first visit +- **Improved Conversion**: Remove friction by gradually collecting user data +- **Enhanced Privacy**: Modern, cookie-free approach to user identification +- **Seamless Experience**: No disruption when transitioning from anonymous to authenticated diff --git a/rownd-docusaurus/docs/welcome/rownd-features.mdx b/rownd-docusaurus/docs/welcome/rownd-features.mdx new file mode 100644 index 0000000..d1b8962 --- /dev/null +++ b/rownd-docusaurus/docs/welcome/rownd-features.mdx @@ -0,0 +1,217 @@ +--- +title: "Rownd Features" +sidebarTitle: "Rownd Features" +--- + +## Rownd: The AI-Enabled Application Services Platform + +Rownd is more than authentication—it's a complete application services platform that powers your app from sign-in to scale. Our AI-enabled platform provides authentication, payments, user management, smart links, and more, all designed to help you launch faster and grow without limits. + +**Free up to 1 million users. No credit card required.** + +- [Complete Application Services](#complete-application-services) +- [AI-Powered Intelligence](#ai-powered-intelligence) +- [Visual SDKs with Built-in UI](#visual-sdks-with-built-in-ui) +- [Easy Customization](#easy-customization) +- [Comprehensive User Management](#comprehensive-user-management) +- [Integrated Payments](#integrated-payments) +- [Smart Links & Deep Linking](#smart-links--deep-linking) +- [Cross-Domain, Cross-App, and Cross-Device](#cross-domain-cross-app-and-cross-device) +- [No-Code Automations](#no-code-automations) +- [Extensive SDK Support](#extensive-sdk-support) +- [Advanced Security and Integrations](#advanced-security-and-integrations) +- [Built-in Analytics](#built-in-analytics) +- [Instant Users](#instant-users-every-visitor-is-a-user) +- [Custom Domains](#custom-domains) + +### Complete Application Services + +Rownd provides all the essential services modern applications need in one unified platform: + +- **Authentication**: Passwordless sign-in, social logins, passkeys, and magic links +- **Payments**: Built-in Stripe integration with automatic account setup +- **User Management**: Complete user profiles and admin tools +- **Smart Links**: Universal links that work across web and mobile +- **Email/Phone Verification**: Built-in verification services with custom branding +- **App Onboarding**: Intelligent flows that adapt to user behavior + + +With Rownd, you get everything you need to build and scale your app—all from one platform, all controllable without redeployment. + + +### AI-Powered Intelligence + +Our AI engine continuously optimizes your app's performance: + +- **Smart Authentication Flows**: AI determines the best sign-in method for each user +- **Predictive Analytics**: Understand user behavior before it happens +- **Automated A/B Testing**: Continuously improve conversion rates +- **Intelligent Routing**: Direct users to the right experience based on context +- **Fraud Detection**: AI-powered security that learns and adapts + +### Visual SDKs with Built-in UI + +Rownd's SDKs come with everything you need out of the box: + +- **Pre-built Components**: Authentication, payments, and user management UI included +- **Mobile Optimized**: Responsive design that works everywhere +- **Customizable Design**: Match your brand perfectly +- **Drop-in Integration**: Add features in minutes, not months + +### Easy Customization + +Our platform empowers every team member to make changes without code: + +#### For Product Managers +- **Conversion Analytics**: Track and optimize every step of the user journey +- **Feature Flags**: Enable/disable features instantly +- **User Segmentation**: Create targeted experiences for different user groups +- **Payment Products**: Launch new pricing plans without engineering + +#### For Designers +- **Visual Style Editor**: Customize every pixel to match your brand +- **Component Library**: Pre-built, customizable UI components +- **Email Templates**: Design beautiful transactional emails +- **Mobile-First Design**: Ensure perfect experiences on every device + +#### For Growth Teams +- **Smart Links**: Create trackable links for campaigns +- **Attribution Tracking**: Know exactly where users come from +- **Onboarding Flows**: Build custom journeys for different segments +- **Referral Programs**: Launch viral growth features instantly + +#### For Developers +- **One-Time Integration**: Install once, iterate forever +- **15+ SDKs**: Support for every major platform +- **REST APIs**: Full programmatic control when needed +- **Webhooks**: React to events in real-time + +### Comprehensive User Management + +Complete user management built right in: + +- **Self-Service Profiles**: Users manage their own data +- **Admin Dashboard**: Full control over all users +- **Role-Based Access**: Define permissions and access levels +- **Bulk Operations**: Import, export, and manage users at scale + +### Integrated Payments + +Start accepting payments in minutes with our Stripe integration: + +- **Automatic Setup**: We create your Stripe Express account instantly +- **Subscription Management**: Built-in billing and plan management +- **Payment UI**: Beautiful checkout components included +- **Just 1% Fee**: We cover all Stripe processing fees +- **Global Payments**: Accept payments from anywhere + +Learn more about [Rownd Payments](/payments/overview). + +### Smart Links & Deep Linking + +Create intelligent links that work everywhere: + +- **Universal Links**: One link that works on web, iOS, and Android +- **Smart Routing**: Direct users to the right place based on their device +- **Campaign Tracking**: Built-in analytics for every link +- **Custom Domains**: Use your own domain for branded experiences +- **QR Codes**: Generate QR codes for offline-to-online experiences + +Learn more about [Smart Links](/magic-links/overview). + +### Cross-Domain, Cross-App, and Cross-Device + +Seamless experiences across your entire ecosystem: + +- **Single Sign-On**: Users sign in once, access everything +- **Cross-Domain Auth**: Works across all your domains +- **Device Handoff**: Start on mobile, continue on desktop +- **App Linking**: Connect web and mobile apps seamlessly +- **State Preservation**: Never lose user context + +### No-Code Automations + +Build powerful workflows without writing code: + +- **Visual Workflow Builder**: Create complex automations visually +- **Trigger Library**: Respond to user actions automatically +- **Email Campaigns**: Send targeted messages based on behavior +- **User Journeys**: Guide users through your app intelligently + +Learn more about [automations](/configuration/automations/overview). + +### Extensive SDK Support + +The most comprehensive SDK coverage in the market: + +**Frontend**: React, Vue, Angular, Next.js, Remix, Svelte, vanilla JavaScript +**Mobile**: iOS (Swift), Android (Kotlin/Java), React Native, Flutter, Ionic +**Backend**: Node.js, Python, Ruby, Go, PHP, .NET, Java +**No-Code**: Webflow, WordPress, Bubble, Framer + +Learn more about our [SDKs](/sdk-reference/overview). + +### Advanced Security and Integrations + +Enterprise-grade security built in: + +- **SOC 2 Certified**: Audited security practices +- **OIDC Server**: Built-in SSO capabilities +- **Encryption**: End-to-end encryption for all data +- **Compliance**: GDPR, CCPA, and HIPAA ready +- **Custom Integrations**: Connect to any system + +### Built-in Analytics + +Understand your users and optimize your app: + +- **Real-Time Dashboards**: See what's happening now +- **Conversion Funnels**: Track user journeys +- **Cohort Analysis**: Understand user segments +- **Custom Reports**: Build the metrics you need +- **Data Export**: Full access to your data + +### Instant Users: Every Visitor is a User + +Revolutionary approach to user management: + +- **Immediate Recognition**: Every visitor gets a unique ID instantly +- **Progressive Profiling**: Collect data gradually without friction +- **No Lost Data**: Track the complete journey from first visit +- **Privacy-First**: Modern, cookie-free identification + +Learn more about [instant users](/configuration/authentication-methods/overview). + +### Custom Domains + +Your brand, front and center: + +- **Authentication Domains**: Sign-in flows on your domain +- **Smart Link Domains**: Branded links for campaigns +- **Email Domains**: Send from your own domain +- **Complete White-Label**: Remove all Rownd branding + +Learn more about [custom domains](/configuration/custom-domains/overview). + +--- + +## Why Choose Rownd? + +### 🚀 Launch Faster +Get to market in days, not months. Our pre-built components and no-code tools mean you can focus on your unique value proposition. + +### 💰 Save Money +Stop paying for multiple services. Rownd includes authentication, payments, analytics, and more—all for less than you'd pay for auth alone. + +### 📈 Scale Confidently +From your first user to your millionth, Rownd scales with you. Enterprise-grade infrastructure with startup-friendly pricing. + +### 🎯 Convert More Users +Our AI-powered optimization and frictionless flows mean higher conversion rates and happier users. + +### 🛡️ Stay Secure +SOC 2 certified with enterprise-grade security. We handle compliance so you can focus on growth. + +--- + +**Ready to power your app with Rownd? [Start free](https://app.rownd.io) with up to 1 million users.** diff --git a/rownd-docusaurus/docusaurus.config.ts b/rownd-docusaurus/docusaurus.config.ts new file mode 100644 index 0000000..9847fb2 --- /dev/null +++ b/rownd-docusaurus/docusaurus.config.ts @@ -0,0 +1,128 @@ +import {themes as prismThemes} from 'prism-react-renderer'; +import type {Config} from '@docusaurus/types'; +import type * as Preset from '@docusaurus/preset-classic'; + +// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) + +const config: Config = { + title: 'Rownd', + tagline: 'Documentation', + favicon: 'favicon.png', + + // Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future + future: { + v4: true, // Improve compatibility with the upcoming Docusaurus v4 + }, + + // Set the production url of your site here + url: 'https://docs.rownd.io', + // Set the // pathname under which your site is served + // For GitHub pages deployment, it is often '//' + baseUrl: '/', + + // GitHub pages deployment config. + // If you aren't using GitHub pages, you don't need these. + organizationName: 'rownd', + projectName: 'docs', + + onBrokenLinks: 'warn', + onBrokenMarkdownLinks: 'warn', + + // Even if you don't use internationalization, you can use this field to set + // useful metadata like html lang. For example, if your site is Chinese, you + // may want to replace "en" with "zh-Hans". + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + presets: [ + [ + 'classic', + { + docs: { + path: 'docs', + routeBasePath: '/', + sidebarPath: './sidebars.ts', + editUrl: undefined, + }, + blog: false, + theme: { + customCss: './src/css/custom.css', + }, + } satisfies Preset.Options, + ], + ], + + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + id: 'sdk', + path: 'sdk-reference', + routeBasePath: 'sdk-reference', + sidebarPath: './sidebars.sdk.ts', + }, + ], + [ + '@docusaurus/plugin-content-docs', + { + id: 'api', + path: 'api-reference', + routeBasePath: 'api-reference', + sidebarPath: './sidebars.api.ts', + }, + ], + [ + '@docusaurus/plugin-client-redirects', + { + redirects: [ + {from: '/sdk-reference/web/react---next-js', to: '/sdk-reference/web/react'}, + {from: '/', to: '/welcome/overview'}, + ], + }, + ], + ], + + themeConfig: { + // Replace with your project's social card + image: 'logo/light.svg', + navbar: { + // Remove text title to avoid a clickable "Rownd" link + title: undefined, + logo: { + alt: 'Rownd', + src: 'logo/light.svg', + srcDark: 'logo/dark.svg', + width: 92, + height: 24, + href: '/welcome/overview', + }, + items: [ + {to: '/welcome/overview', label: 'Documentation', position: 'left'}, + {to: '/sdk-reference/overview', label: 'SDK Reference', position: 'left'}, + {to: '/api-reference/authentication/overview', label: 'API Reference', position: 'left'}, + {href: 'https://rownd.io', label: 'Website', position: 'right'}, + {href: 'https://app.rownd.io', label: 'Dashboard', position: 'right'}, + ], + }, + footer: { + style: 'dark', + links: [], + copyright: `© ${new Date().getFullYear()} Rownd`, + }, + prism: { + theme: prismThemes.github, + darkTheme: prismThemes.dracula, + }, + } satisfies Preset.ThemeConfig, +}; + +// Add Font Awesome stylesheet +// Docusaurus supports a top-level "stylesheets" export on config +(config as any).stylesheets = [ + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css', + 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap', +]; + +export default config; diff --git a/rownd-docusaurus/package-lock.json b/rownd-docusaurus/package-lock.json new file mode 100644 index 0000000..25c594e --- /dev/null +++ b/rownd-docusaurus/package-lock.json @@ -0,0 +1,17519 @@ +{ + "name": "rownd-docusaurus", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "rownd-docusaurus", + "version": "0.0.0", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/preset-classic": "3.8.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "prism-react-renderer": "^2.3.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/plugin-client-redirects": "^3.8.1", + "@docusaurus/tsconfig": "3.8.1", + "@docusaurus/types": "3.8.1", + "typescript": "~5.6.2" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@algolia/abtesting": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.1.0.tgz", + "integrity": "sha512-sEyWjw28a/9iluA37KLGu8vjxEIlb60uxznfTUmXImy7H5NvbpSO6yYgmgH5KiD7j+zTUUihiST0jEP12IoXow==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.9.tgz", + "integrity": "sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.9", + "@algolia/autocomplete-shared": "1.17.9" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.9.tgz", + "integrity": "sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.9" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.9.tgz", + "integrity": "sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.9" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.9.tgz", + "integrity": "sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.35.0.tgz", + "integrity": "sha512-uUdHxbfHdoppDVflCHMxRlj49/IllPwwQ2cQ8DLC4LXr3kY96AHBpW0dMyi6ygkn2MtFCc6BxXCzr668ZRhLBQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.35.0.tgz", + "integrity": "sha512-SunAgwa9CamLcRCPnPHx1V2uxdQwJGqb1crYrRWktWUdld0+B2KyakNEeVn5lln4VyeNtW17Ia7V7qBWyM/Skw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.35.0.tgz", + "integrity": "sha512-ipE0IuvHu/bg7TjT2s+187kz/E3h5ssfTtjpg1LbWMgxlgiaZIgTTbyynM7NfpSJSKsgQvCQxWjGUO51WSCu7w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.35.0.tgz", + "integrity": "sha512-UNbCXcBpqtzUucxExwTSfAe8gknAJ485NfPN6o1ziHm6nnxx97piIbcBQ3edw823Tej2Wxu1C0xBY06KgeZ7gA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.35.0.tgz", + "integrity": "sha512-/KWjttZ6UCStt4QnWoDAJ12cKlQ+fkpMtyPmBgSS2WThJQdSV/4UWcqCUqGH7YLbwlj3JjNirCu3Y7uRTClxvA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.35.0.tgz", + "integrity": "sha512-8oCuJCFf/71IYyvQQC+iu4kgViTODbXDk3m7yMctEncRSRV+u2RtDVlpGGfPlJQOrAY7OONwJlSHkmbbm2Kp/w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.35.0.tgz", + "integrity": "sha512-FfmdHTrXhIduWyyuko1YTcGLuicVbhUyRjO3HbXE4aP655yKZgdTIfMhZ/V5VY9bHuxv/fGEh3Od1Lvv2ODNTg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", + "license": "MIT" + }, + "node_modules/@algolia/ingestion": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.35.0.tgz", + "integrity": "sha512-gPzACem9IL1Co8mM1LKMhzn1aSJmp+Vp434An4C0OBY4uEJRcqsLN3uLBlY+bYvFg8C8ImwM9YRiKczJXRk0XA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.35.0.tgz", + "integrity": "sha512-w9MGFLB6ashI8BGcQoVt7iLgDIJNCn4OIu0Q0giE3M2ItNrssvb8C0xuwJQyTy1OFZnemG0EB1OvXhIHOvQwWw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.35.0.tgz", + "integrity": "sha512-AhrVgaaXAb8Ue0u2nuRWwugt0dL5UmRgS9LXe0Hhz493a8KFeZVUE56RGIV3hAa6tHzmAV7eIoqcWTQvxzlJeQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.35.0.tgz", + "integrity": "sha512-diY415KLJZ6x1Kbwl9u96Jsz0OstE3asjXtJ9pmk1d+5gPuQ5jQyEsgC+WmEXzlec3iuVszm8AzNYYaqw6B+Zw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.35.0.tgz", + "integrity": "sha512-uydqnSmpAjrgo8bqhE9N1wgcB98psTRRQXcjc4izwMB7yRl9C8uuAQ/5YqRj04U0mMQ+fdu2fcNF6m9+Z1BzDQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.35.0.tgz", + "integrity": "sha512-RgLX78ojYOrThJHrIiPzT4HW3yfQa0D7K+MQ81rhxqaNyNBu4F1r+72LNHYH/Z+y9I1Mrjrd/c/Ue5zfDgAEjQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", + "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", + "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz", + "integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.3.tgz", + "integrity": "sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", + "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", + "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", + "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", + "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz", + "integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", + "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.27.1.tgz", + "integrity": "sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", + "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.3.tgz", + "integrity": "sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", + "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", + "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.0", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.3", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.0", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.3", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz", + "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.27.1", + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", + "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.3.tgz", + "integrity": "sha512-LKYxD2CIfocUFNREQ1yk+dW+8OH8CRqmgatBZYXb+XhuObO8wsDpEoCNri5bKld9cnj8xukqZjxSX8p1YiRF8Q==", + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.43.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.5.tgz", + "integrity": "sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", + "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.2.tgz", + "integrity": "sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.10.tgz", + "integrity": "sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-function": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.10.tgz", + "integrity": "sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-variadic-function-arguments": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.0.tgz", + "integrity": "sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-content-alt-text": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.6.tgz", + "integrity": "sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-exponential-functions": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.9.tgz", + "integrity": "sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-4.0.0.tgz", + "integrity": "sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gamut-mapping": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.10.tgz", + "integrity": "sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gradients-interpolation-method": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.10.tgz", + "integrity": "sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.10.tgz", + "integrity": "sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.2.tgz", + "integrity": "sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-initial": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-2.0.1.tgz", + "integrity": "sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.3.tgz", + "integrity": "sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-light-dark-function": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.9.tgz", + "integrity": "sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-3.0.0.tgz", + "integrity": "sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overflow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-2.0.0.tgz", + "integrity": "sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overscroll-behavior": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-2.0.0.tgz", + "integrity": "sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-resize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-3.0.0.tgz", + "integrity": "sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.4.tgz", + "integrity": "sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-minmax": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.9.tgz", + "integrity": "sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.5.tgz", + "integrity": "sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-4.0.0.tgz", + "integrity": "sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz", + "integrity": "sha512-HlEoG0IDRoHXzXnkV4in47dzsxdsjdz6+j7MLjaACABX2NfvjFS6XVAnpaDyGesz9gK2SC7MbNwdCHusObKJ9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.10.tgz", + "integrity": "sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.1.0.tgz", + "integrity": "sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-random-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-2.0.1.tgz", + "integrity": "sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-relative-color-syntax": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.10.tgz", + "integrity": "sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-4.0.1.tgz", + "integrity": "sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-sign-functions": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.4.tgz", + "integrity": "sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.9.tgz", + "integrity": "sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz", + "integrity": "sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.9.tgz", + "integrity": "sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.4", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-4.0.0.tgz", + "integrity": "sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/utilities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", + "integrity": "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.9.0.tgz", + "integrity": "sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA==", + "license": "MIT" + }, + "node_modules/@docsearch/react": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.9.0.tgz", + "integrity": "sha512-mb5FOZYZIkRQ6s/NWnM98k879vu5pscWqTLubLFBO87igYYT4VzVazh4h5o/zCvTIZgEt3PvsCOMOswOUo9yHQ==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.9", + "@algolia/autocomplete-preset-algolia": "1.17.9", + "@docsearch/css": "3.9.0", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 20.0.0", + "react": ">= 16.8.0 < 20.0.0", + "react-dom": ">= 16.8.0 < 20.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docusaurus/babel": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.1.tgz", + "integrity": "sha512-3brkJrml8vUbn9aeoZUlJfsI/GqyFcDgQJwQkmBtclJgWDEQBKKeagZfOgx0WfUQhagL1sQLNW0iBdxnI863Uw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/runtime-corejs3": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/bundler": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.1.tgz", + "integrity": "sha512-/z4V0FRoQ0GuSLToNjOSGsk6m2lQUG4FRn8goOVoZSRsTrU8YR2aJacX5K3RG18EaX9b+52pN4m1sL3MQZVsQA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.8.1", + "@docusaurus/cssnano-preset": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.3", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.11.0", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.2", + "null-loader": "^4.0.1", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^6.0.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.1.tgz", + "integrity": "sha512-ENB01IyQSqI2FLtOzqSI3qxG2B/jP4gQPahl2C3XReiLebcVh5B5cB9KYFvdoOqOWPyr5gXK4sjgTKv7peXCrA==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.8.1", + "@docusaurus/bundler": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "execa": "5.1.1", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.6", + "tinypool": "^1.0.2", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^4.15.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.1.tgz", + "integrity": "sha512-G7WyR2N6SpyUotqhGznERBK+x84uyhfMQM2MmDLs88bw4Flom6TY46HzkRkSEzaP9j80MbTN8naiL1fR17WQug==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.5.4", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.1.tgz", + "integrity": "sha512-2wjeGDhKcExEmjX8k1N/MRDiPKXGF2Pg+df/bDDPnnJWHXnVEZxXj80d6jcxp1Gpnksl0hF8t/ZQw9elqj2+ww==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.1.tgz", + "integrity": "sha512-DZRhagSFRcEq1cUtBMo4TKxSNo/W6/s44yhr8X+eoXqCLycFQUylebOMPseHi5tc4fkGJqwqpWJLz6JStU9L4w==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^2.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.1.tgz", + "integrity": "sha512-6xhvAJiXzsaq3JdosS7wbRt/PwEPWHr9eM4YNYqVlbgG1hSK3uQDXTVvQktasp3VO6BmfYWPozueLWuj4gB+vg==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.8.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-client-redirects": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.8.1.tgz", + "integrity": "sha512-F+86R7PBn6VNgy/Ux8w3ZRypJGJEzksbejQKlbTC8u6uhBUhfdXWkDp6qdOisIoW0buY5nLqucvZt1zNJzhJhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.8.1.tgz", + "integrity": "sha512-vNTpMmlvNP9n3hGEcgPaXyvTljanAKIUkuG9URQ1DeuDup0OR7Ltvoc8yrmH+iMZJbcQGhUJF+WjHLwuk8HSdw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "cheerio": "1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "schema-dts": "^1.1.2", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.1.tgz", + "integrity": "sha512-oByRkSZzeGNQByCMaX+kif5Nl2vmtj2IHQI2fWjCfCootsdKZDPFLonhIp5s3IGJO7PLUfe0POyw0Xh/RrGXJA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "schema-dts": "^1.1.2", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.8.1.tgz", + "integrity": "sha512-a+V6MS2cIu37E/m7nDJn3dcxpvXb6TvgdNI22vJX8iUTp8eoMoPa0VArEbWvCxMY/xdC26WzNv4wZ6y0iIni/w==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-css-cascade-layers": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.8.1.tgz", + "integrity": "sha512-VQ47xRxfNKjHS5ItzaVXpxeTm7/wJLFMOPo1BkmoMG4Cuz4nuI+Hs62+RMk1OqVog68Swz66xVPK8g9XTrBKRw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.8.1.tgz", + "integrity": "sha512-nT3lN7TV5bi5hKMB7FK8gCffFTBSsBsAfV84/v293qAmnHOyg1nr9okEw8AiwcO3bl9vije5nsUvP0aRl2lpaw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^2.3.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.8.1.tgz", + "integrity": "sha512-Hrb/PurOJsmwHAsfMDH6oVpahkEGsx7F8CWMjyP/dw1qjqmdS9rcV1nYCGlM8nOtD3Wk/eaThzUB5TSZsGz+7Q==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.8.1.tgz", + "integrity": "sha512-tKE8j1cEZCh8KZa4aa80zpSTxsC2/ZYqjx6AAfd8uA8VHZVw79+7OTEP2PoWi0uL5/1Is0LF5Vwxd+1fz5HlKg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.8.1.tgz", + "integrity": "sha512-iqe3XKITBquZq+6UAXdb1vI0fPY5iIOitVjPQ581R1ZKpHr0qe+V6gVOrrcOHixPDD/BUKdYwkxFjpNiEN+vBw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.8.1.tgz", + "integrity": "sha512-+9YV/7VLbGTq8qNkjiugIelmfUEVkTyLe6X8bWq7K5qPvGXAjno27QAfFq63mYfFFbJc7z+pudL63acprbqGzw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/plugin-svgr": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.8.1.tgz", + "integrity": "sha512-rW0LWMDsdlsgowVwqiMb/7tANDodpy1wWPwCcamvhY7OECReN3feoFwLjd/U4tKjNY3encj0AJSTxJA+Fpe+Gw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.8.1.tgz", + "integrity": "sha512-yJSjYNHXD8POMGc2mKQuj3ApPrN+eG0rO1UPgSx7jySpYU+n4WjBikbrA2ue5ad9A7aouEtMWUoiSRXTH/g7KQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/plugin-content-blog": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/plugin-content-pages": "3.8.1", + "@docusaurus/plugin-css-cascade-layers": "3.8.1", + "@docusaurus/plugin-debug": "3.8.1", + "@docusaurus/plugin-google-analytics": "3.8.1", + "@docusaurus/plugin-google-gtag": "3.8.1", + "@docusaurus/plugin-google-tag-manager": "3.8.1", + "@docusaurus/plugin-sitemap": "3.8.1", + "@docusaurus/plugin-svgr": "3.8.1", + "@docusaurus/theme-classic": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-search-algolia": "3.8.1", + "@docusaurus/types": "3.8.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.8.1.tgz", + "integrity": "sha512-bqDUCNqXeYypMCsE1VcTXSI1QuO4KXfx8Cvl6rYfY0bhhqN6d2WZlRkyLg/p6pm+DzvanqHOyYlqdPyP0iz+iw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/plugin-content-blog": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/plugin-content-pages": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.45", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.5.4", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.1.tgz", + "integrity": "sha512-UswMOyTnPEVRvN5Qzbo+l8k4xrd5fTFu2VPPfD6FcW/6qUtVLmJTQCktbAL3KJ0BVXGm5aJXz/ZrzqFuZERGPw==", + "license": "MIT", + "dependencies": { + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.1.tgz", + "integrity": "sha512-NBFH5rZVQRAQM087aYSRKQ9yGEK9eHd+xOxQjqNpxMiV85OhJDD4ZGz6YJIod26Fbooy54UWVdzNU0TFeUUUzQ==", + "license": "MIT", + "dependencies": { + "@docsearch/react": "^3.9.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "algoliasearch": "^5.17.1", + "algoliasearch-helper": "^3.22.6", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.1.tgz", + "integrity": "sha512-OTp6eebuMcf2rJt4bqnvuwmm3NVXfzfYejL+u/Y1qwKhZPrjPoKWfk1CbOP5xH5ZOPkiAsx4dHdQBRJszK3z2g==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/tsconfig": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.8.1.tgz", + "integrity": "sha512-XBWCcqhRHhkhfolnSolNL+N7gj3HVE3CoZVqnVjfsMzCoOsuQw2iCLxVVHtO+rePUUfouVZHURDgmqIySsF66A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docusaurus/types": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.1.tgz", + "integrity": "sha512-ZPdW5AB+pBjiVrcLuw3dOS6BFlrG0XkS2lDGsj8TizcnREQg3J8cjsgfDviszOk4CweNfwo1AEELJkYaMUuOPg==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@docusaurus/types/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.1.tgz", + "integrity": "sha512-P1ml0nvOmEFdmu0smSXOqTS1sxU5tqvnc0dA4MTKV39kye+bhQnjkIKEE18fNOvxjyB86k8esoCIFM3x4RykOQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "escape-string-regexp": "^4.0.0", + "execa": "5.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "p-queue": "^6.6.2", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.1.tgz", + "integrity": "sha512-zTZiDlvpvoJIrQEEd71c154DkcriBecm4z94OzEE9kz7ikS3J+iSlABhFXM45mZ0eN5pVqqr7cs60+ZlYLewtg==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.8.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.1.tgz", + "integrity": "sha512-gs5bXIccxzEbyVecvxg6upTwaUbfa0KMmTj7HhHzc016AGyxH2o73k1/aOD0IFrdCsfJNt37MqNI47s2MgRZMA==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "license": "MIT" + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "license": "MIT" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.16", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", + "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", + "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.13.tgz", + "integrity": "sha512-zePQJSW5QkwSHKRApqWCVKeKoSOt4xvEnLENZPjyvm9Ezdf/EyDeJM7jqLzOwjVICQQzvLZ63T55MKdJB5H6ww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prismjs": { + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz", + "integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==", + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", + "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@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" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@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" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@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" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.35.0.tgz", + "integrity": "sha512-Y+moNhsqgLmvJdgTsO4GZNgsaDWv8AOGAaPeIeHKlDn/XunoAqYbA+XNpBd1dW8GOXAUDyxC9Rxc7AV4kpFcIg==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.1.0", + "@algolia/client-abtesting": "5.35.0", + "@algolia/client-analytics": "5.35.0", + "@algolia/client-common": "5.35.0", + "@algolia/client-insights": "5.35.0", + "@algolia/client-personalization": "5.35.0", + "@algolia/client-query-suggestions": "5.35.0", + "@algolia/client-search": "5.35.0", + "@algolia/ingestion": "1.35.0", + "@algolia/monitoring": "1.35.0", + "@algolia/recommend": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz", + "integrity": "sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==", + "license": "MIT", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", + "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001733", + "electron-to-chromium": "^1.5.199", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001735", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", + "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compressible/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.0.tgz", + "integrity": "sha512-c2KZL9lP4DjkN3hk/an4pWn5b5ZefhRJnAc42n6LJ19kSnbeRbdQZE5dSeE2LBol1OwJD3X1BQvFTAsa8ReeDA==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.0.tgz", + "integrity": "sha512-gRoVMBawZg0OnxaVv3zpqLLxaHmsubEGyTnqdpI/CEBvX4JadI1dMSHxagThprYRtSVbuQxvi6iUatdPxohHpA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.25.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.45.0.tgz", + "integrity": "sha512-OtwjqcDpY2X/eIIg1ol/n0y/X8A9foliaNt1dSK0gV3J2/zw+89FcNG3mPK+N8YWts4ZFUPxnrAzsxs/lf8yDA==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-blank-pseudo": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-7.0.1.tgz", + "integrity": "sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "license": "ISC", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz", + "integrity": "sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-has-pseudo/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", + "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssdb": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.3.1.tgz", + "integrity": "sha512-XnDRQMXucLueX92yDe0LPKupXetWoFOgawr4O4X41l5TltgK2NVbJJVDnnOywDYfW1sTJ28AcXGKOqdRKwCcmQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ], + "license": "MIT-0" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", + "license": "MIT", + "dependencies": { + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.204", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.204.tgz", + "integrity": "sha512-s9VbBXWxfDrl67PlO4avwh0/GU2vcwx8Fph3wlR8LJl7ySGYId59EFE17VWVcuC3sLWNPENm6Z/uGqKbkPCcXA==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.1.0.tgz", + "integrity": "sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.0.tgz", + "integrity": "sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "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" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "license": "MIT", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-monkey": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", + "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", + "license": "Unlicense" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "license": "ISC" + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "license": "MIT", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.4.tgz", + "integrity": "sha512-V/PZeWsqhfpE27nKeX9EO2sbR+D17A+tLf6qU+ht66jdUsN0QLKJN27Z+1+gHrVMKgndBahes0PU6rRihDgHTw==", + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz", + "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==", + "license": "MIT", + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.45", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.45.tgz", + "integrity": "sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "license": "MIT", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "license": "MIT", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/launch-editor": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz", + "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "license": "CC0-1.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "license": "MIT", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", + "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.2.tgz", + "integrity": "sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/null-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-4.0.1.tgz", + "integrity": "sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/null-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/null-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/null-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/null-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "license": "MIT", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz", + "integrity": "sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.10.tgz", + "integrity": "sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-10.0.0.tgz", + "integrity": "sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-10.0.0.tgz", + "integrity": "sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-custom-media": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.6.tgz", + "integrity": "sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-properties": { + "version": "14.0.6", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz", + "integrity": "sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.5.tgz", + "integrity": "sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.5", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-9.0.1.tgz", + "integrity": "sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-unused": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.2.tgz", + "integrity": "sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-10.0.1.tgz", + "integrity": "sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-focus-within": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-9.0.1.tgz", + "integrity": "sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-6.0.0.tgz", + "integrity": "sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-image-set-function": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-7.0.0.tgz", + "integrity": "sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-lab-function": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz", + "integrity": "sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.1.0.tgz", + "integrity": "sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-merge-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", + "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", + "license": "MIT", + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nesting": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", + "integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-resolve-nested": "^3.1.0", + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", + "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-3.0.0.tgz", + "integrity": "sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-6.0.0.tgz", + "integrity": "sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-10.0.0.tgz", + "integrity": "sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.4.tgz", + "integrity": "sha512-q+lXgqmTMdB0Ty+EQ31SuodhdfZetUlwCA/F0zRcd/XdxjzI+Rl2JhZNz5US2n/7t9ePsvuhCnEN4Bmu86zXlA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-cascade-layers": "^5.0.2", + "@csstools/postcss-color-function": "^4.0.10", + "@csstools/postcss-color-mix-function": "^3.0.10", + "@csstools/postcss-color-mix-variadic-function-arguments": "^1.0.0", + "@csstools/postcss-content-alt-text": "^2.0.6", + "@csstools/postcss-exponential-functions": "^2.0.9", + "@csstools/postcss-font-format-keywords": "^4.0.0", + "@csstools/postcss-gamut-mapping": "^2.0.10", + "@csstools/postcss-gradients-interpolation-method": "^5.0.10", + "@csstools/postcss-hwb-function": "^4.0.10", + "@csstools/postcss-ic-unit": "^4.0.2", + "@csstools/postcss-initial": "^2.0.1", + "@csstools/postcss-is-pseudo-class": "^5.0.3", + "@csstools/postcss-light-dark-function": "^2.0.9", + "@csstools/postcss-logical-float-and-clear": "^3.0.0", + "@csstools/postcss-logical-overflow": "^2.0.0", + "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", + "@csstools/postcss-logical-resize": "^3.0.0", + "@csstools/postcss-logical-viewport-units": "^3.0.4", + "@csstools/postcss-media-minmax": "^2.0.9", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.5", + "@csstools/postcss-nested-calc": "^4.0.0", + "@csstools/postcss-normalize-display-values": "^4.0.0", + "@csstools/postcss-oklab-function": "^4.0.10", + "@csstools/postcss-progressive-custom-properties": "^4.1.0", + "@csstools/postcss-random-function": "^2.0.1", + "@csstools/postcss-relative-color-syntax": "^3.0.10", + "@csstools/postcss-scope-pseudo-class": "^4.0.1", + "@csstools/postcss-sign-functions": "^1.1.4", + "@csstools/postcss-stepped-value-functions": "^4.0.9", + "@csstools/postcss-text-decoration-shorthand": "^4.0.2", + "@csstools/postcss-trigonometric-functions": "^4.0.9", + "@csstools/postcss-unset-value": "^4.0.0", + "autoprefixer": "^10.4.21", + "browserslist": "^4.25.0", + "css-blank-pseudo": "^7.0.1", + "css-has-pseudo": "^7.0.2", + "css-prefers-color-scheme": "^10.0.0", + "cssdb": "^8.3.0", + "postcss-attribute-case-insensitive": "^7.0.1", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^7.0.10", + "postcss-color-hex-alpha": "^10.0.0", + "postcss-color-rebeccapurple": "^10.0.0", + "postcss-custom-media": "^11.0.6", + "postcss-custom-properties": "^14.0.6", + "postcss-custom-selectors": "^8.0.5", + "postcss-dir-pseudo-class": "^9.0.1", + "postcss-double-position-gradients": "^6.0.2", + "postcss-focus-visible": "^10.0.1", + "postcss-focus-within": "^9.0.1", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^6.0.0", + "postcss-image-set-function": "^7.0.0", + "postcss-lab-function": "^7.0.10", + "postcss-logical": "^8.1.0", + "postcss-nesting": "^13.0.2", + "postcss-opacity-percentage": "^3.0.0", + "postcss-overflow-shorthand": "^6.0.0", + "postcss-page-break": "^3.0.4", + "postcss-place": "^10.0.0", + "postcss-pseudo-class-any-link": "^10.0.1", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^8.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-10.0.1.tgz", + "integrity": "sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", + "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-8.0.1.tgz", + "integrity": "sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", + "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", + "license": "MIT", + "dependencies": { + "sort-css-media-queries": "2.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.23" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/postcss-zindex": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", + "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.1.tgz", + "integrity": "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==", + "license": "MIT", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "license": "MIT", + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.1" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-helmet-async": { + "name": "@slorber/react-helmet-async", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@slorber/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-e9/OK8VhwUSc67diWI8Rb3I0YgI9/SBQtnhe9aEuK6MhZm7ntZZimXgwXnd8W96YTmSOb9M4d8LwhRZyhWr/1A==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-json-view-lite": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.4.2.tgz", + "integrity": "sha512-m7uTsXDgPQp8R9bJO4HD/66+i218eyQPAb+7/dGQpwg8i4z2afTFqtHJPQFHvJfgDCjGQ1HSGlL3HtrZDa3Tdg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", + "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", + "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-directive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", + "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-emoji": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", + "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.2", + "emoticon": "^4.0.1", + "mdast-util-find-and-replace": "^3.0.1", + "node-emoji": "^2.1.0", + "unified": "^11.0.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", + "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", + "license": "MIT" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtlcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", + "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/schema-dts": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.5.tgz", + "integrity": "sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==", + "license": "Apache-2.0" + }, + "node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "license": "MIT", + "peer": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", + "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "license": "MIT", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "3.3.0", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "license": "MIT" + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/sitemap": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", + "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", + "license": "MIT", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", + "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", + "license": "MIT", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/stylehacks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "license": "MIT" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.14.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "license": "BSD-2-Clause", + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/url-loader/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "license": "MIT" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/watchpack": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpack": { + "version": "5.101.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", + "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.3", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.2", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpackbar": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", + "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "consola": "^3.2.3", + "figures": "^3.2.0", + "markdown-table": "^2.0.0", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/webpackbar/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/webpackbar/node_modules/markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", + "license": "MIT", + "dependencies": { + "repeat-string": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpackbar/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpackbar/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "license": "MIT", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/rownd-docusaurus/package.json b/rownd-docusaurus/package.json new file mode 100644 index 0000000..41e90e5 --- /dev/null +++ b/rownd-docusaurus/package.json @@ -0,0 +1,48 @@ +{ + "name": "rownd-docusaurus", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids", + "typecheck": "tsc" + }, + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/preset-classic": "3.8.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "prism-react-renderer": "^2.3.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/plugin-client-redirects": "^3.8.1", + "@docusaurus/tsconfig": "3.8.1", + "@docusaurus/types": "3.8.1", + "typescript": "~5.6.2" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 3 chrome version", + "last 3 firefox version", + "last 5 safari version" + ] + }, + "engines": { + "node": ">=18.0" + } +} diff --git a/rownd-docusaurus/sdk-reference/backend/convex.mdx b/rownd-docusaurus/sdk-reference/backend/convex.mdx new file mode 100644 index 0000000..476dc6c --- /dev/null +++ b/rownd-docusaurus/sdk-reference/backend/convex.mdx @@ -0,0 +1,244 @@ +--- +title: "Convex" +description: Convex SDK reference +icon: c +--- + +## Installation + +Install the required dependencies: + +```bash +npm install convex @rownd/react +``` + +--- + +## Configuration + +1. **Get your Rownd App Key:** + - Sign up or log in at [Rownd Dashboard](https://app.rownd.io) + - Create/select your application + - Copy your **App Key** (e.g., `key_xxxxxxxx`) + - Copy your **App ID** This is used to verify the audience. + +2. **Set up Convex:** + - Follow the [Convex Getting Started guide](https://docs.convex.dev/quickstart/) to initialize your backend and get your deployment URL. + +--- + +## RowndProvider Setup + +Wrap your app with `RowndProvider` from `@rownd/react/convex` and pass both your Convex client and Rownd app key: + +```tsx +import { createRoot } from "react-dom/client"; +import { ConvexReactClient } from "convex/react"; +import { RowndProvider } from "@rownd/react/convex"; +import App from "./App"; + +const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string); + +createRoot(document.getElementById("root")!).render( + + + +); +``` + +## Server-side Usage + + +### Add Rownd to your auth.config.js file. + +Add these to your convex/auth.config.js file: + +```ts +//convex/auth.config.js +export default { + providers: [ + { + domain: "https://api.rownd.io", + applicationID: "app:your-rownd-app-id" + }, + ], +``` + + +> [! NOTE] +> Ensure you have the `app:` in addition to your app-id. +> For example, applicationID: "app:app_alksdjflakjvlkeja" + +### Mapping Rownd IDs in Convex + +**It is critical to keep a mapping of the Rownd user ID in your Convex `users` table.** +This allows you to associate Rownd-authenticated users with your app's data. + +**Schema example:** + +```ts +// convex/schema.ts +import { defineSchema, defineTable } from "convex/server"; +import { v } from "convex/values"; + +export default defineSchema({ + users: defineTable({ + rowndId: v.string(), + email: v.optional(v.string()), + }) + .index("by_rowndId", ["rowndId"]), + // ...other tables +}); +``` + +**Storing and looking up users by Rownd ID:** + +This example mutation ensures the existence of a user record in your database for the currently authenticated +user. `ctx.auth.getUserIdentity()` will return all of the claim data included in the user's JWT. You can use the +`subject` value to map your internal users to Rownd user's. + +```ts +// convex/users.ts +import { mutation } from "./_generated/server"; + +export const store = mutation({ + args: {}, + handler: async (ctx) => { + const identity = await ctx.auth.getUserIdentity(); + if (!identity) { + throw new Error("Called storeUser without authentication present"); + } + + // Check if we've already stored this identity before. + const user = await ctx.db + .query("users") + .withIndex("by_rowndId", (q) => + q.eq("rowndId", identity.subject), + ) + .unique(); + if (user !== null) { + return user._id; + } + + // If it's a new identity, create a new `User`. + const dbUser = await ctx.db.insert("users", { + rowndId: identity.subject, + email: identity.email, + }); + + return dbUser; + }, +}); +``` + +### Accessing the Current User + +To get the current authenticated user in any Convex function, always look up by the Rownd ID: + +```ts +// convex/auth.ts +import { query } from "./_generated/server"; + +export const loggedInUser = query({ + handler: async (ctx) => { + const identity = await ctx.auth.getUserIdentity(); + if (!identity) { + return null; + } + const user = await ctx.db + .query("users") + .withIndex("by_rowndId", (q) => + q.eq("rowndId", identity.subject), + ) + .unique(); + return user; + }, +}); +``` + +### Protecting Convex Functions + +Always check for authentication and use the Rownd ID mapping to associate data with users: + +```ts +import { mutation } from "./_generated/server"; +import { v } from "convex/values"; + +export const createPost = mutation({ + args: { + title: v.string(), + content: v.string(), + category: v.string(), + }, + handler: async (ctx, args) => { + const identity = await ctx.auth.getUserIdentity(); + if (!identity) throw new Error("Please log in"); + const user = await ctx.db + .query("users") + .withIndex("by_rowndId", (q) => + q.eq("rowndId", identity.subject), + ) + .unique(); + if (!user?._id) throw new Error("User not found"); + + return await ctx.db.insert("posts", { + authorId: user._id, + title: args.title, + content: args.content, + category: args.category, + likes: 0, + }); + }, +}); +``` + +--- + + +## Client-side Usage + +### Using Rownd React SDK Features + +After setting up the `RowndProvider`, you can use all other features of the [`@rownd/react`](https://docs.rownd.io/sdk-reference/web/react) SDK in your app as documented in the official Rownd docs. + + +The Rownd React SDK only handles client-side authentication state. For proper integration with Convex, you should use Convex's authentication hooks and utilities to ensure server-side state is properly synchronized. + + +Create a custom hook like `useStoreUserEffect` to handle the authentication flow as outlined in these [Convex docs](https://docs.convex.dev/auth/database-auth) + +**Example:** + +```tsx +import { useRownd } from "@rownd/react"; +import { useStoreUserEffect } from "./useStoreUserEffect.js"; + +function Profile() { + const { requestSignIn, signOut, user: rowndUser } = useRownd(); + const { isAuthenticated } = useStoreUserEffect(); + + if (!isAuthenticated) { + return ; + } + + return ( +
+

Welcome, {rowndUser?.first_name}!

+ +
+ ); +} +``` + +For more details and advanced usage, see the [Rownd React SDK documentation](https://docs.rownd.io/sdk-reference/web/react). + +--- + +## Best Practices & Tips + +- **Always map Rownd IDs:** + Store the Rownd user ID (`identity.subject`) in your `users` table and use it as the primary lookup for all user-specific data. +- **Use indexes for efficient lookups:** + Index your `users` table by `rowndId` for fast queries. +- **Optionally include additional profile data in JWT claims** + You can use the Rownd Platform to setup profile data fields for inclusion in additional JWT claims. This makes them avaiable on the `ctx.auth.getUserIdentity()` diff --git a/rownd-docusaurus/sdk-reference/backend/overview.mdx b/rownd-docusaurus/sdk-reference/backend/overview.mdx new file mode 100644 index 0000000..9427d7e --- /dev/null +++ b/rownd-docusaurus/sdk-reference/backend/overview.mdx @@ -0,0 +1,137 @@ +--- +title: "Backend SDK Overview" +sidebarTitle: Overview +--- + +## Rownd Backend SDK Features +Rownd's Backend SDKs provide powerful tools for secure and efficient server-side authentication and user management. + +### Robust Token Management + +Ensure secure access to your backend resources with comprehensive token management: +- **Token Verification**: Easily verify user tokens to authenticate requests +- **Token Refresh**: Automatically handle token expiration and renewal +- **Custom Claims**: Add and manage custom claims for user tokens + +### Understanding Rownd Tokens + +Rownd uses JWT (JSON Web Tokens) for authentication. Here's an example token payload: + +```json +json +{ +"jti": "e5aded8f-4950-4215-9a45-dc3e7x8575e90", +"aud": [ +"app:app_v8q15ahdmpx3wqnbm6j19grlx", +"app_variant:cm4swjkos008x5bfc8x48d70xu" +], +"sub": "user_o7jyzlzbga2uhly698ba8a1s", +"iat": 1734467046, +"exp": 1734470646, +"iss": "https://api.rownd.io", +"https://auth.rownd.io/app_user_id": "user_o7jyzlzbga2uhly698ba8a1s", +"https://auth.rownd.io/is_verified_user": true, +"https://auth.rownd.io/auth_level": "verified" +} +``` + +Standard JWT claims: +- **jti**: Unique identifier for this token +- **aud**: Array of audiences this token is intended for (includes Rownd app ID and app variant ID if applicable); +- **sub**: Subject identifier (Rownd user ID) +- **iat**: Timestamp when the token was issued +- **exp**: Timestamp when the token expires +- **iss**: Token issuer (Rownd API) + +Rownd-specific claims: +- **https://auth.rownd.io/app_user_id**: User's unique identifier in Rownd +- **https://auth.rownd.io/is_verified_user**: Boolean indicating if the user is verified +- **https://auth.rownd.io/auth_level**: User's authentication level (e.g., "verified") + + + +### Seamless Integration + +Integrate Rownd's backend capabilities with your existing infrastructure: +- **Framework Compatibility**: Support for popular server-side frameworks like Node.js, Django, and .NET +- **API Integration**: Effortlessly call Rownd's backend services +- **Server-Side Rendering Support**: Compatible with frameworks like Next.js and Remix for efficient SSR + +### Advanced User Management + +Manage user data and authentication flows with ease: +- **User Profiles**: Access and update user profiles programmatically +- **Role-Based Access Control**: Implement fine-grained access control for different user roles +- **Event Hooks**: Trigger custom logic on authentication events + +### Developer-Friendly Tools + +Streamline backend development with comprehensive tools and support: +- **Detailed Documentation**: In-depth guides and API references +- **Versioning and Compatibility**: Clear upgrade paths and backward compatibility +- **Technical Support**: Access to expert engineering support + +## Steps for getting started: +1. [Set up your Rownd account](/welcome/getting-started) (only takes a minute). +2. Create an [app key](/configuration/app-credentials). +3. Install Rownd using an SDK. +4. [Configure customizations](/configuration/overview) and sign-in methods from the Rownd platform. + +## Rownd Backend SDKs: + + + + JavaScript and TypeScript + + + Python + + + Python + + + C# + + } + href="/sdk-reference/backend/ruby-on-rails" + /> + } + href="/sdk-reference/backend/convex" + > + Convex + + diff --git a/rownd-docusaurus/sdk-reference/images/image.png b/rownd-docusaurus/sdk-reference/images/image.png new file mode 100644 index 0000000..23d7cc3 Binary files /dev/null and b/rownd-docusaurus/sdk-reference/images/image.png differ diff --git a/rownd-docusaurus/sdk-reference/images/wordpress_plugin_appkey.png b/rownd-docusaurus/sdk-reference/images/wordpress_plugin_appkey.png new file mode 100644 index 0000000..bb7e77e Binary files /dev/null and b/rownd-docusaurus/sdk-reference/images/wordpress_plugin_appkey.png differ diff --git a/rownd-docusaurus/sdk-reference/images/wordpress_plugin_search.png b/rownd-docusaurus/sdk-reference/images/wordpress_plugin_search.png new file mode 100644 index 0000000..94114cc Binary files /dev/null and b/rownd-docusaurus/sdk-reference/images/wordpress_plugin_search.png differ diff --git a/rownd-docusaurus/sdk-reference/mobile/android.mdx b/rownd-docusaurus/sdk-reference/mobile/android.mdx new file mode 100644 index 0000000..a17ae00 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/mobile/android.mdx @@ -0,0 +1,526 @@ +--- +title: "Android" +description: "Rownd bindings for Android" +icon: "android" +--- + +The Rownd SDK for Android provides authentication, account and user profile management, deep linking, and more for native Android applications. + +Using the Rownd platform, you can easily bring the same authentication that's on your website to your mobile apps. Or if you only authenticate users on your mobile apps, you can streamline the authentication process using Rownd's passwordless sign-in links, enabling you to seamlessly authenticate users from an app link sent to their email or phone number. + +Once a user is authenticated, you can retrieve and update their profile information on the fly using native APIs. Leverage Rownd's pre-built mobile app components to give users profile management tools. + +## Installation + +In Android Studio, open your app's module-level `build.gradle` file and add the following dependency: + +``` +implementation 'io.rownd:android:3.0.2' +``` + +After adding, run a Gradle sync and the Rownd SDK/API should be available within your IDE. + +### ProGuard config + +Rownd's Android SDK includes a `consumer-rules.pro` file, which should automatically augment your app's own proguard/r2 config. + +If you're using ProGuard to shrink, obfuscate, and/or optimize your app ([and you should!](https://developer.android.com/studio/build/shrink-code)), and you're noticing minification or runtime errors after installing Rownd, you may need to add the following rules to your `proguard-rules.pro` file. + +```proguard +-if @kotlinx.serialization.Serializable class ** +-keepclassmembers class <1> { + static <1>$Companion Companion; +} + +# Keep `serializer()` on companion objects (both default and named) of serializable classes. +-if @kotlinx.serialization.Serializable class ** { + static **$* *; +} +-keepclassmembers class <2>$<3> { + kotlinx.serialization.KSerializer serializer(...); +} + +# Keep `INSTANCE.serializer()` of serializable objects. +-if @kotlinx.serialization.Serializable class ** { + public static ** INSTANCE; +} +-keepclassmembers class <1> { + public static <1> INSTANCE; + kotlinx.serialization.KSerializer serializer(...); +} + +# @Serializable and @Polymorphic are used at runtime for polymorphic serialization. +-keepattributes RuntimeVisibleAnnotations,AnnotationDefault,Annotation,InnerClasses + +# Suppress warnings about missing AWT classes (which aren't used in Android) +-dontwarn java.awt.* + +# libsodium uses jna +-keep class com.sun.jna.* { *; } +-keepclassmembers class * extends com.sun.jna.* { public *; } + +# ViewModel names are used at runtime +-keep public class * extends androidx.lifecycle.ViewModel {*;} +``` + +## Usage + +### Initializing the Rownd SDK + +The Rownd SDK needs access to your application's and current activity's context in order to properly manage state, display UI components, and so on. + +The most straightforward way of doing this is to subclass the Android `Application` class and pass the app's primary context. + +To initialize Rownd, call the configure method like this: + +```kotlin +Rownd.configure(application, "REPLACE_WITH_YOUR_APP_KEY") +``` + +Here's an example of what that might look like in the initial `Application` class: + +```kotlin +class MyApplication : Application() { + override fun onCreate() { + super.onCreate() + Rownd.configure(this, "REPLACE_WITH_YOUR_APP_KEY") + } +} +``` + +After initialization, your app should typically call `Rownd.requestSignIn()` at some point, if the user is not already authenticated. This will display the Rownd interface for authenticating the user. Once they complete the sign-in process, an access token and the user's profile information will be available to your app. + +### Handling authentication + +Rownd leverages an observable architecture to expose data to your app using [StateFlow](https://developer.android.com/kotlin/flow/stateflow-and-sharedflow). This means that as the Rownd state changes, an app can dynamically update without complicated logic. For example, a view can display different information based on the user's authentication status. + +You can use this StateFlow in both older-style XML layouts as well as Android Jetpack's newer Composable views. + +### Using state in XML layout + +```xml + + + + + + + + + + + + + + + + +``` + +```kotlin +// my_activity.kt +class MyActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val binding: ActivityMainBinding = + DataBindingUtil.setContentView(this, R.layout.activity_main) + + binding.lifecycleOwner = this + + binding.rownd = Rownd + } +} + +``` + +### Using state in a Composable + +```kotlin +// some_activity_or_component.kt + +class MyActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + val state = Rownd.state.collectAsState() + val signInButtonText = if (state.value.auth.isAuthenticated) "Sign out" else "Sign in" + Button( + onClick = { + if (state.value.auth.isAuthenticated) Rownd.signOut() + else Rownd.requestSignIn() + } + ) { + Text(signInButtonText) + } + } + } +} +``` + +Once you subscribe to the Rownd state via `Rownd.state.collectAsState()`, you can use the various parts of the state tree as needed. + +Access the state like this: + +```kotlin +val rowndState = Rownd.state.collectAsState() + +val isAuthenticated = rowndState.value.auth.isAuthenticated +``` + +The following classes/properties are available: + +#### .auth + +```kotlin +data class AuthState( + val accessToken: String?, // Current, valid access token for the user (valid for one hour) + val isVerifiedUser: Boolean, // Whether the current user has verified at least one identifier (e.g., email) + val isAuthenticated: Boolean // Whether the current user is signed in +) +``` + +#### .user + +```kotlin +data class User( + val id: String?, // The user's ID as known to Rownd + val data: Map = HashMap(), + val redacted: PersistentList // A list of any profile fields that a user has restricted your app from accessing +) +``` + +## Customizing the UI + +While most customizations are handled via the [Rownd dashboard](https://app.rownd.io), there are a few things that have to be customized directly in the SDK. + +The `RowndCustomizations` class exists to facilitate these customizations. It provides the following properties that may be subclassed or overridden. + +* `sheetBackgroundColor: Color?` (default: `null`) - Allows setting a single color for Rownd-provided bottom sheet interfaces regardless of system theme. Use this or `dynamicSheetBackgroundColor`, but not both. + +* `dynamicSheetBackgroundColor: Color` (default: `light: #ffffff`, `dark: #1c1c1e`; requires subclassing) - Allows changing the background color underlying the bottom sheet that appears when signing in, managing the user account, etc. Based on the system color scheme. + +* `sheetCornerBorderRadius: Dp` (default: `25.dp`) - Modifies the curvature radius of the bottom sheet's top corners. + +* `loadingAnimation: Int` (default: null) - Replace Rownd's use of the system default loading spinner (i.e., `ProgressBar`) with a custom animation. Any animation resource compatible with [Lottie](https://airbnb.design/lottie/) should work, but will be scaled to fit a 1:1 aspect ratio (usually with a frame width/height of `100 Dp`) This should be a value like `R.raw.my_animation` + +To apply customizations, we recommend subclassing the `RowndCustomizations` class. Here's an example: + +```kotlin +class AppCustomizations(app: Application) : RowndCustomizations() { + private var app: Application + + init { + this.app = app + } + + override val dynamicSheetBackgroundColor: Color + get() { + val uiMode = AppCompatDelegate.getDefaultNightMode() + return if (uiMode == AppCompatDelegate.MODE_NIGHT_YES) { + Color(0xff123456) + } else { + Color(0xfffedcba) + + } + } + + override var sheetCornerBorderRadius: Dp = 25.dp + + override var loadingAnimation: Int? = R.raw.loading +} + +// MyApplication.kt +import android.app.Application +import android.content.res.Configuration +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import io.rownd.android.Rownd +import io.rownd.android.models.RowndCustomizations + +class MyApplication: Application() { + + override fun onCreate() { + super.onCreate() + + Rownd.configure(this, "b60bc454-c45f-47a2-8f8a-12b2062f5a77") + Rownd.config.customizations = AppCustomizations(this) + + } +} +``` + +## API reference + +In addition to the StateFlow APIs, Rownd provides imperative APIs that you can call to request sign in, get and retrieve user profile information, retrieve a current access token, or encrypt user data with the user's local key. + +### Rownd.requestSignIn(): Unit + +Opens the Rownd sign-in dialog for authentication. + +### Rownd.requestSignIn(with = RowndSignInHint) + +Initiates a sign-in using the method specified by the `with` argument, bypassing the authentication method selector. For example, this could be used to steer a new user toward a specific sign-in method. + +Supported options: + +* `RowndSignInHint.Google` - Prompt user to sign in with their Google account + +* `RowndSignInHint.OneTap` - Prompt user to sign into their account with Google One Tap + +* `RowndSignInHint.Passkey` - Prompt user to sign in with a passkey if they've previously set one up + +* `RowndSignInHint.Guest` - Sign in the user anonymously as a guest. + +Example: + +```kotlin +Rownd.requestSignIn(with = RowndSignInHint.Google) +``` + +### Rownd.requestSignIn(RowndSignInOpts(...)): Unit + +Opens the Rownd sign-in dialog for authentication, as before, but allows passing additional context options as shown below. + +* `intent: RowndSignInIntent` - This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `.SignIn` or `.SignUp`. If you don’t set this value, the user will be presented with the unified sign-in/sign-up flow. Please reach out to [support@rownd.io](mailto:support@rownd.io) to enable. + +* `postSignInRedirect: String` (Not recommended) - If you've followed the steps to enable Android App Links, the redirect will be handled automatically. When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for postSignInRedirect. If this is an [Android App Link](https://developer.android.com/training/app-links), it will redirect the user back to your app. + +Example: + +```kotlin +Rownd.requestSignIn(RowndSignInOpts( + intent = RowndSignInIntent.SignUp +)) +``` + +### Rownd.signOut(): Void + +Clears the user's access token, removes the user's profile data, and returns the user to a completely unauthenticated state. + +### Rownd.signOut(scope = RowndSignOutScope): Void + +Revokes all tokens for the specified user causing them to be signed out on all devices. + +Supported options: + +* `RowndSignOutScope.all` + + \- All devices + +
+ + + The following user profile APIs technically accept `Any` as the value of a field. However, that value **must** be serializable using [Kotlin's Serialization](https://kotlinlang.org/docs/serialization.html) library. If the value is not serializable out of the box, you'll need to provide your own serializer implementation as described in the Kotlin documentation. + + +### suspend Rownd.getAccessToken(throwIfMissing: Boolean = false): String? + +Assuming a user is signed-in, returns a valid access token, refreshing the current one if needed. + +By default, this function will return `null` if an access token cannot be returned, either because the user is not signed in or because the refresh token is invalid. + +If an access token cannot be returned due to a temporary condition (e.g., inaccessible network), this function will throw a `RowndException` indicating the failure reason (e.g., server or network error). + +You may also set `throwIfMissing` to `true` to force an error to be thrown if an access token cannot be returned. This will provide more granular reasons for the failure. The possible error subtypes for `RowndException` in this case are: + +- `NoAccessTokenPresentException(message: String)` - the user is not signed in +- `InvalidRefreshTokenException(message: String)` - the refresh token was invalid (e.g., the token was expired, revoked, or a previous exchange failed to complete successfully). The user will be signed out. +- `NetworkConnectionFailureException(details: String)` - a network condition prevented the token from being refreshed, even after several retries and should be re-attempted later. The user can remain signed-in. +- `ServerException(details: String)` - an error occurred on the server and you should try again later. The user can remain signed-in. + +Example: + +```kotlin + try { + val accessToken = Rownd.getAccessToken(throwIfMissing = true) + } catch (e: RowndException) { + when (e) { + is NoAccessTokenPresentException -> { /* User is not signed in. do nothing. */ } + is InvalidRefreshTokenException -> { /* Refresh token is invalid. User was signed out. Show splash page and error dialog */ } + else -> { /* Something else went wrong. Ignore if possible, otherwise ask user to retry their action, connect to a network, close/reopen the app, etc. */ } + } + } +``` + +### suspend Rownd.getAccessToken(token: String): String? + +When possible, exchanges a non-Rownd access token for a Rownd access token. This is primarily used in scenarios +where an app is migrating from some other authentication mechanism to Rownd. Using Rownd integrations, +the system will accept a third-party token. If it successfully validates, Rownd will sign-in the user and +return a fresh Rownd access token to the caller. + +This API returns `null` if the token could not be validated and exchanged. If that occurs, it's likely +that the user should sign-in normally via `Rownd.requestSignIn()`. + +> NOTE: This API is typically used once. After a Rownd token is available, other tokens should be discarded. + +Example: + +```kotlin + // Assume `oldToken` was retrieved from some prior authenticator. + val accessToken = Rownd.getAccessToken(oldToken) + + if (accessToken != null) { + // Navigate to the UI that a user should typically see + } else { + Rownd.requestSignIn() + } +``` + +### Rownd.user.get(): Map\ + +Returns the entire user profile as a Map + +### Rownd.user.get\(field: String): T? + +Returns the value of a specific field in the user's data Map. `"id"` is a special case that will return the user's ID, even though it's technically not in the Map itself. + +Your application code is responsible for knowing which type the value should cast to. If the cast fails or the entry doesn't exist, a `null` value will be returned. + +### Rownd.user.set(data: Map\): Void + +Replaces the user's data with that contained in the Map. This may overwrite existing values, but must match the schema you defined within your Rownd application dashboard. Any fields that are flagged as `encrypted` will be encrypted on-device prior to storing in Rownd's platform. + +### Rownd.user.set(field: String, value: Any): Void + +Sets a specific user profile field to the provided value, overwriting if a value already exists. If the field is flagged as `encrypted`, it will be encrypted on-device prior to storing in Rownd's platform. + +## Data encryption + +As indicated previously, Rownd can automatically assist you in protecting sensitive user data by encrypting it on-device with a user's unique encryption key prior to saving it in Rownd's own platform storage. + +When you configure your app within the Rownd platform, you can indicate that it supports on-device encryption. When this flag is set, Rownd will automatically generate a cryptographically secure, unrecoverable encryption key on the user's device after they sign in. The key is stored using Android's native KeyStore mechanisms and all encryption is handled on the device. The key is never transmitted to Rownd's servers and the Rownd SDK does not provide any APIs to for your code to programmatically retrieve the encryption key. + +Only fields that you designate `encrypted` are encrypted on-device prior to storing within Rownd. Some identifying fields like email and phone number do not support on-device encryption at this time, since they are frequently used for indexing purposes. + +Of course, all data within the Rownd platform is encrypted at rest on disk and in transit, but this does not afford the same privacy guarantees as data encrypted on a user's local device. For especially sensitive data, we recommend enabling field-level encryption. + + + Data encrypted on-device will not be accessible by you, the app developer, outside of the context of your app. In other words, your app can use encrypted data in its plaintext (decrypted) form while the user is signed in, but you won't be able to retrieve that data from the Rownd servers in a decrypted form. For data that you choose to encrypt, you should never transmit the plain text value across a network. + + +In some cases, you may want to encrypt data on-device that you'll send to your own servers for storage. Rownd provides convenience methods to encrypt and decrypt that data with the same user-owned key. + +### Rownd.user.encrypt(plaintext: String): String + +Encrypts the provided String `data` using the user's symmetric encryption key and returns the ciphertext as a string. You can encrypt anything that can be represented as a string (e.g., Int, Dictionary, Array, etc), but it's currently up to you to get it into a string format first. + +If the encryption fails, an `EncryptionException` will be thrown with a message explaining the failure. + +### Rownd.user.decrypt(ciphertext: String): String + +Attempts to decrypt the provided String `data`, returning the plaintext as a string. If the data originated as some other type (e.g., Map), you'll need to decode the data back into its original type. + +If the decryption fails, an `EncryptionException` will be thrown with a message explaining the failure. + + + Encryption is only possible once a user has authenticated. Rownd supports multiple levels of authentication (e.g., guest, unverified, and verified), but the lowest level of authentication must be achieved prior to encrypting or decrypting data. If you need to explicitly check whether encryption is possible at a specific point in time, call `Rownd.user.isEncryptionPossible(): Boolean` prior to calling `encrypt()` or `decrypt()`. + + +## Events + +The Rownd SDK emits lifecycle events that you can listen to within your app. These events are primarily useful for detecting more granular aspects of a user's session (e.g., starting to sign in, completing sign-in, updated profile, etc.). + +To listen to events, pass a function or closure that accepts a `RowndEvent` object to `Rownd.addEventListener()`. It might look something like this: + +```kotlin +class MyApp: Application() { + + override fun onCreate() { + super.onCreate() + + Rownd.addEventListener { + when (it.event) { + RowndEventType.SignInStarted -> { + // Do stuff + } + RowndEventType.SignInCompleted -> { + it.data?.get("user_type")?.let { it1 -> Log.d("App", it1.toString()) } + } + + else -> { + // no-op + } + } + } + } +} +``` + +This registers the event listener with the Rownd SDK. You can also unregister the listener by calling `Rownd.removeEventListener()` with the same function or closure if you assign it to a variable. + +Once the event handler is registered, it will receive events as they occur. The `RowndEvent` object contains the event type and any associated data. The event types are defined in the `RowndEventType` enum. + +> NOTE: You'll need `implementation "org.jetbrains.kotlinx:kotlinx-serialization-json"` listed as a dependency in your `build.gradle` file in order to access the `data` `JsonObject` in the `RowndEvent` object. + +#### List of events + +Here's a list of events that the Rownd SDK emits and the corresponding data that should be present in the event data dictionary. Remember to write your code defensively, as the data dictionary may be missing keys in some cases. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventTypePayload
User started signing inRowndEventType.SignInStarted + ```javascript + { + method: "google" | "apple" | "phone" | "email" | "passkey" | etc + } + ``` +
User signed in successfullyRowndEventType.SignInCompleted + ```javascript + { + method: "google" | "apple" | "phone" | "email" | "passkey" | etc, + user_type: "new_user" | "existing_user" + app_variant_user_type: 'new_user' | 'existing_user' | optional + } + ``` +
User sign in failedRowndEventType.SignInFailed + ```javascript + { + reason: string + } + ``` +
diff --git a/rownd-docusaurus/sdk-reference/mobile/expo.mdx b/rownd-docusaurus/sdk-reference/mobile/expo.mdx new file mode 100644 index 0000000..be17cd6 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/mobile/expo.mdx @@ -0,0 +1,141 @@ +--- +title: "Expo" +description: "Rownd bindings for Expo" +icon: "mobile" +--- + +
+
+ +### Prerequisites + +You must be using React Native v0.64 or higher. + +Must be an ejected Expo app which can be bare React Native or use an Expo development build. Instructions for bare React Native app can be found [here](/sdk-reference/mobile/react-native). + +### Installation + +First, install the Rownd SDK for Expo. + +```bash +npm install @rownd/react-native +``` + +### Expo development + +1. Add `@rownd/react-native` as a plugin to your `app.json` file. + +```json +{ + "expo": { + "plugins": ["@rownd/react-native"] + } +} +``` + +2. Install [Expo BuildProperties](https://docs.expo.dev/versions/latest/sdk/build-properties/) to set iOS/Android versions + +```sh +npx expo install expo-build-properties +``` + +3. Add `expo-build-properties` as a plugin to your `app.json` file. Ensure the Sdk versions match or are above provided iOS/Android versions. + +```json +{ + "expo": { + "plugins": [ + "@rownd/react-native", + [ + "expo-build-properties", + { + "android": { + "minSdkVersion": 26 + }, + "ios": { + "deploymentTarget": "14.0" + } + } + ] + ] + } +} +``` + +4. (optional) Enable Apple sign-in for iOS in your `app.json` file. + +```json +{ + "expo": { + "ios": { + "usesAppleSignIn": true + } + } +} +``` + +5. (optional) Enable Google sign-in for iOS. Add your Google IOS Client ID client as a URL Scheme in your `app.json` file. + +```json +{ + "expo": { + "infoPlist": { + "CFBundleURLTypes": [ + { + "CFBundleURLSchemes": [ + "com.googleusercontent.apps.xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxx" + ] + } + ] + } + } +} +``` + +#### Enable deep linking + +Rownd supports automatically signing-in users when they initially install your +app or when they click a sign-in link when the app is already installed. Follow instructions below to setup. + +1. Visit the Rownd platform and go to the [Sign-in methods](https://app.rownd.io) page. Open the Mobile app settings modal and (1) create a subdomain and (2) fill out the iOS/Android settings. + +2. Enable deep linking for Expo using `app.json` and `` created in the Rownd platform. + +These settings might only apply at the time the native projects were generated. Try deleting the ios/android folders and rebuilding the project. + +File: `app.json` +```json +{ + "expo": { + "ios": { + ... + "associatedDomains": ["applinks:.rownd.link"] + }, + "android": { + ... + "intentFilters": [ + { + "action": "VIEW", + "autoVerify": true, + "data": [ + { + "scheme": "https", + "host": ".rownd.link" + } + ], + "category": ["BROWSABLE", "DEFAULT"] + } + ] + } + } +} +``` + + \ No newline at end of file diff --git a/rownd-docusaurus/sdk-reference/mobile/flutter.mdx b/rownd-docusaurus/sdk-reference/mobile/flutter.mdx new file mode 100644 index 0000000..d700787 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/mobile/flutter.mdx @@ -0,0 +1,245 @@ +--- +title: "Flutter" +description: "Rownd bindings for Flutter" +icon: "mobile" +--- + +## Getting Started + +This SDK leverages Rownd's web and native iOS and Android SDKs to provide a simple interface for Flutter developers to add Rownd to their apps. + +### Installation + +Begin by depending on `rownd_flutter_plugin` and `provider` in your `pubspec.yaml`: + +```yaml +name: my_app +--- +dependencies: + rownd_flutter_plugin: ^1.3.2 + provider: ^6.1.2 +``` + +If you don't have one already, be sure to obtain an app key from the [Rownd dashboard](https://app.rownd.io) for use in the next step. + +## Platform-specific configuration + +There are a couple of configuration settings that must be applied to the platform-specific code for your app in order for Rownd to work properly. + +### Android + +1. Set your app's `targetSdkVersion` to 32 or higher in your app's `build.gradle` file. + +2. Set your app's `minSdkVersion` to 26 or higher in your app's `build.gradle` file. Rownd currently does not support an API version lower than 26. + +3. Ensure any Android activities (like `MainActivity`) subclass `FlutterFragmentActivity` instead of `FlutterActivity`. If you're using the default `MainActivity` generated by Flutter, you can simply change the superclass to `FlutterFragmentActivity` like this: + +```kotlin +class MainActivity: FlutterFragmentActivity() {} +``` + +4. Check and update your ProGuard config using [the rules from our Android SDK](https://github.com/rownd/android/blob/main/README.md#proguard-config). + +## Usage + +Initialize the Rownd plugin and call `rowndPlugin.configure(RowndConfig(appKey: 'YOUR_APP_KEY'));` within your application wherever you do most of your app's initialization. + +Now you're ready to use Rownd in your app. The plugin provides a `RowndCubit` class that can be used to manage the Rownd state. + +A basic sign-in example might look like this: + +```dart +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import 'package:rownd_flutter_plugin/rownd.dart'; +import 'package:rownd_flutter_plugin/rownd_platform_interface.dart'; +import 'package:rownd_flutter_plugin/state/global_state.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + final rowndPlugin = RowndPlugin(); // Initialize the Rownd plugin + + @override + void initState() { + super.initState(); + rowndPlugin.configure(RowndConfig(appKey: 'YOUR_APP_KEY'));// Configure the Rownd plugin with your app key + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => RowndCubit(rowndPlugin), // Create a RowndCubit with the Rownd plugin + child: MaterialApp( + title: 'Example App', + theme: ThemeData( + useMaterial3: true, + colorScheme: ColorScheme.fromSeed(seedColor: Colors.green), + ), + home: BlocBuilder( + builder: (context, state) { + // Use the RowndCubit to build the UI based on the current authentication state + if (state == AuthState.authenticated) { + return const MyHomePage(); + } else { + return const LoginPage(); + } + }, + ), + routes: { + '/home': (context) => const MyHomePage(), + }, + ), + ); + } +} + +``` + +In this example, the `home` for the BlocProvider is determined by the `RowndCubit`'s authentication state. If the user is authenticated, the `MyHomePage` widget is displayed. If the user is not authenticated, the `LoginPage` widget is displayed. + +There are many ways to define the UI based on the authentication state, but this is a simple and effective approach. + +To learn more about Bloc and Cubit, see the [flutter_bloc documentation](https://pub.dev/packages/flutter_bloc). + +### RowndCubit + +The `RowndCubit` class is a `Cubit` that manages the Rownd state. It provides a simple interface for checking the current user's authentication status, signing in and out, and getting the current user's profile. + +```dart +class LoginPage extends StatelessWidget { + const LoginPage({super.key}); + + @override + Widget build(BuildContext context) { + var authCubit = context.watch(); // Get the RowndCubit from the context + + return Scaffold( + appBar: AppBar( + title: const Text('My example app'), + ), + body: Column(children: [ + const Center(child: Text('Welcome to my example app!')), + ElevatedButton( + onPressed: () async { + authCubit.signIn(); // Sign the user in + }, + child: const Text('Sign in')), + ]), + ); + } +} +``` + +## API + +### `signIn(RowndSignInOptions? options)` + +Signs the user in. The `options` parameter is optional and can be used to specify additional options for the sign-in process. + +```dart +class LoginPage extends StatelessWidget { + const LoginPage({super.key}); + + @override + Widget build(BuildContext context) { + var authCubit = context.watch(); + + return Scaffold( + body: Column([ + const Center(child: Text('Welcome to my example app!')), + ElevatedButton( + onPressed: () async { + authCubit.signIn(); // Sign the user in + }, + child: const Text('Sign in')), + ]), + ); + } +} +``` + +#### `RowndSignInOptions` + +| Property | Type | Description | +| -------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `postSignInRedirect` (not recommended) | `String` | If you've followed the steps to enable Android App Links, the redirect will be handled automatically. When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for postSignInRedirect. If this is an [Android App Link](https://developer.android.com/training/app-links), it will redirect the user back to your app. | +| `intent` | `String` | This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `.SignIn` or `.SignUp`. If you don’t set this value, the user will be presented with the unified sign-in/sign-up flow. Please reach out to [support@rownd.io](mailto:support@rownd.io) to enable. | + +### `signOut()` + +Signs the user out. + +```dart +var authCubit = context.watch(); +... +ElevatedButton( + onPressed: () async { + authCubit.signOut(); // Sign the user out + Navigator.pushReplacementNamed(context, '/'); + }, + child: const Text("Sign out"), +) +``` + +### `isAuthenticated()` + +Returns a boolean indicating whether the user is authenticated. + +```dart +var authCubit = context.watch(); + +bool isAuthenticated = authCubit.isAuthenticated(); // Check if the user is authenticated +``` + +### `manageAccount()` + +Displays the current user's profile information, allowing them to update it. + +```dart +var authCubit = context.watch(); +... +ElevatedButton( + onPressed: () { + authCubit.manageAccount(); // Display the user's profile information + }, + child: const Text("Manage Account"), +), +``` + +### `registerPasskey()` + +Registers a passkey for the user. A user must have successfully authenticated at least once before they can register a passkey. + +```dart +var authCubit = context.watch(); +... +ElevatedButton( + onPressed: () { + authCubit.registerPasskey(); // Register a passkey for the user + }, + child: const Text("Register Passkey"), +), +``` + +### `user` + +Returns the current user's profile as a `Map`. + +```dart +var authCubit = context.watch(); + +Map user = authCubit.user; // Get the user's profile +``` diff --git a/rownd-docusaurus/sdk-reference/mobile/ios.mdx b/rownd-docusaurus/sdk-reference/mobile/ios.mdx new file mode 100644 index 0000000..e72135f --- /dev/null +++ b/rownd-docusaurus/sdk-reference/mobile/ios.mdx @@ -0,0 +1,484 @@ +--- +title: "iOS" +description: "Rownd bindings for native iOS apps" +icon: "apple" +--- + +The Rownd SDK for iOS provides authentication, account and user profile management, deep linking, and more for native iPhone, iPad, and even macOS applications. + +Using the Rownd platform, you can easily bring the same authentication that's on your website to your mobile apps. Or if you only authenticate users on your mobile apps, you can streamline the authentication process using Rownd's passwordless sign-in links, enabling you to seamlessly authenticate users from an app link sent to their email or phone number. + +Once a user is authenticated, you can retrieve and update their profile information on the fly using native APIs. Leverage Rownd's pre-built mobile app components to give users profile management tools. + +## Installation + +In Xcode, select your project file, select the main target, then scroll down to the "frameworks" section to add a package dependency to your project. See the [official documentation](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) for specific steps. + +Enter this as the package repository url: + +``` +https://github.com/rownd/ios.git +``` + +## Usage + +### Initializing the Rownd SDK + +In your `AppDelegate` file, call the `Rownd.configure()` method during application launch: + +```swift +func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + + Task { + await Rownd.configure(launchOptions: launchOptions, appKey: "YOUR_API_KEY") + } + + return true +} + +// Optionally, ensure any incoming URL requests are passed to Rownd for authentication +func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + Rownd.handleSmartLink(url: url) + return true +} + +func application(_ application: UIApplication, + continue userActivity: NSUserActivity, + restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { + // Get URL components from the incoming user activity. + guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, + let incomingURL = userActivity.webpageURL, + let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else { + return false + } + + return Rownd.handleSmartLink(url: incomingURL) +} + +func scene(_ scene: UIScene, willConnectTo + session: UISceneSession, + options connectionOptions: UIScene.ConnectionOptions) { + + // Get URL components from the incoming user activity. + guard let userActivity = connectionOptions.userActivities.first, + userActivity.activityType == NSUserActivityTypeBrowsingWeb, + let incomingURL = userActivity.webpageURL, + let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else { + return + } + + Rownd.handleSmartLink(url: incomingURL) +} +``` + +After initialization, your app will typically call `Rownd.requestSignIn()` at some point, if the user is not already authenticated. This will display the Rownd interface for authenticating the user. Once they complete the sign-in process, an access token and the user's profile information will be available to your app. + +### Handling authentication + +Rownd leverages an observeable architecture to expose data to your app. This means that as the Rownd state changes, an app can dynamically update without complicated logic. For example, a view can display different information based on the user's authentication status. + +Here's an example SwiftUI view that displays different messages depending on the user's authenticated status: + +```swift +import SwiftUI +import Rownd + +struct MyView: View { + @StateObject var authState = Rownd.getInstance().state().subscribe { $0.auth } + @StateObject var user = Rownd.getInstance().state().subscribe { $0.user.data } + + var body: some View { + VStack { + HStack { + Button(action: { + if authState.current.isAuthenticated { + Rownd.signOut() + } else { + Rownd.requestSignIn() + } + }, + label: { + Text(!authState.current.isAuthenticated ? "Sign in" : "Sign out") + }) + Spacer() + if authState.current.isAuthenticated { + Button(action: { + + }, label: { + Text(user.current?["first_name"]?.value as? String) + }) + } + } + .padding(.horizontal) + } + } +} + +struct MyView_Previews: PreviewProvider { + static var previews: some View { + MyView() + } +} +``` + +#### Example usage outside of SwiftUI + +```swift +class Auth { + private var authState = Rownd.getInstance().state().subscribe { $0.auth } + private var cancellables = Set() + init() { + self.authState.$current + .sink { [weak self] state in + // Called whenever the auth state changes + guard !state.isLoading else { return } + + guard state.auth.isAuthenticated else { + return + } + + // User is authenticated. Change app state accordingly. + // This is also a good time to get the latest access token. + let accessToken = await Rownd.getAccessToken() + } + .store(in: &cancellables) + } +} +``` + +You can subscribe to any state object that Rownd supports. Here's a list of available states and their structures: + +#### .auth + +```swift +public struct AuthState { + public var accessToken: String? // Current, valid access token for the user (valid for one hour) + public var isAuthenticated: Bool // Whether the user is currently authenticated + public var isAccessTokenValid: Bool // Whether the current access token is valid + public var isVerifiedUser: Bool? // Whether the current user has verified at least one identifier (e.g., email) + public var hasPreviouslySignedIn: Bool // Whether the app has been previously signed in before +} +``` + +#### .user + +```swift +public struct UserState { + public var id: String? // The user's ID as known to Rownd + public var data: Dictionary // Contains key/value pairs for the current user based on your Rownd's app config +} +``` + +### Getting an access token + +Whenever your app needs to make an authenticated request to your backend, you'll need to get an access token. You can do this by calling `await Rownd.getAccessToken(throwIfMissing: true)`. If the user is not authenticated, this function will throw an `AuthenticationError.noAccessTokenPresent` error. + +If there is an issue fetching the access token (e.g., during a token refresh), an `AuthenticationError.serverError` or `AuthenticationError.networkConnectionFailure` error will be thrown. Server and network failures are automatically retried before throwing an error. + +If the user is signed in, but the refresh token is expired, invalidated, or has been used previously, the user will be signed out and the function will throw an `AuthenticationError.invalidRefreshToken` error. + +See the [API reference](#rownd-getaccesstoken-token-string-async-string) for more information. + +### Customizing the UI + +While most customizations are handled via the [Rownd dashboard](https://app.rownd.io), there are a few things that have to be customized directly in the SDK. + +The `RowndCustomizations` class exists to facilitate these customizations. It provides the following properties that may be subclassed or overridden. + +* `sheetBackgroundColor: UIColor` (default: light: .white, dark: .systemGray6; requires subclassing) - Allows changing the background color underlaying the bottom sheet that appears when signing in, managing the user account, etc. + +* `sheetCornerBorderRadius: CGFloat` (default: `25.0`) - Modifies the curvature radius of the bottom sheet corners. + +* `loadingAnimation: Lottie.Animation` (default: nil) - Replace Rownd's use of the system default loading spinner (i.e., `UIActivityIndicatorView` or `ProgressView`) with a custom animation. Any animation compatible with [Lottie](https://airbnb.design/lottie/) should work, but will be scaled to fit a 1:1 aspect ratio (usually with a `CGRect` frame width/height of `100`) + +To apply customizations, we recommend subclassing the `RowndCustomizations` class. Here's an example: + +```swift +class AppCustomizations : RowndCustomizations { + override var sheetBackgroundColor: UIColor { + return UIColor(red: 31/255, green: 37/255, blue: 80/255, alpha: 1.0) + } +} + +// AppDelegate.swift +import Rownd + +class AppDelegate: NSObject, UIApplicationDelegate { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + + Rownd.config.customizations = AppCustomizations() // Apply the customizations + + Task { + await Rownd.configure(launchOptions: launchOptions, appKey: "YOUR_API_KEY") + } + + return true + } +} +``` + +### Usage within app extensions + +It's possible to access the Rownd state from within an app extension, like a widget. You'll need to include the Rownd package in the extension's dependencies and set up an app group for data sharing between the app and the extension. Without the app group, extensions will not be able to sync with your app's authentication state. + +Follow these steps to configure your app and extension to work with Rownd: + +1. Add an [app group](https://developer.apple.com/documentation/xcode/configuring-app-groups) entitlement to both your app and any extensions that will use Rownd. This app group **must** be named like this: `.io.rownd.sdk`. For example, if you work at a company with the acme.com domain, your app group might look like this: `com.acme.app.io.rownd.sdk`. Rownd will store its data in this app group. Your app should store data in a separate app group to prevent any collisions. + +2. In your app's `AppDelegate` file as well as your extension's entry point, set the app group prefix you defined above via `Rownd.config.appGroupPrefix = ""` (e.g., `Rownd.config.appGroupPrefix = "com.acme.app"`) + +3. In your extension, call `Rownd.configure()` prior to accessing authentication state. Here's an example: + + ```swift + Task { + Rownd.config.appGroupPrefix = "group.rowndexample" + let rowndState = await Rownd.configure(appKey: "key_pko8eul59xz33hr21jgxvx6s") + + var authStatus: String = "You are not authenticated. ☹️" + if rowndState.auth.isAuthenticated == true { + authStatus = "You are authenticated! 😁" + } + } + ``` + + + If you're building widgets that need access to Rownd auth state, you should listen for Rownd auth events and notify `WidgetCenter` that widgets may need updating any time the state changes. That way, they'll re-render while your app is in the foreground and will show an accurate state. Here's a simple example: + + ```swift + import Foundation + import Combine + import WidgetKit + import Rownd + + class SomeClass { + private var authState = Rownd.getInstance().state().subscribe { $0.auth } + private var cancellables = Set() + + init() { + self.authState + .$current + .sink { [weak self] state in + WidgetCenter.shared.reloadAllTimelines() + } + .store(in: &cancellables) + } + } + ``` + + +### Configuration options +Rownd provides a number of configuration options that can be set before calling `Rownd.configure()`. These options are available via the `Rownd.config` object. + +* `enableSmartLinkPasteBehavior: Bool` (default: `true`) - Attempts to access the clipboard for smart link pasting behavior if it contains a URL. This _will_ trigger a system alert asking for permission to access the clipboard. If you don't want this behavior, set this to `false`. + +### Events + +The Rownd SDK emits lifecycle events that you can listen to within your app. These events are primarily useful for detecting more granular aspects of a user's session (e.g., starting to sign in, completing sign-in, updated profile, etc.). + +To listen to events, first create a class that conforms to the `RowndEventHandlerDelegate` protocol. It looks something like this: + +```swift +import Foundation +import Rownd + +class RowndEventHandler: RowndEventHandlerDelegate { + func handleRowndEvent(_ event: RowndEvent) { + switch event.event { + case .signInCompleted: + let userType = event.data?["user_type"] + let appVariantUserType = event.data?["app_variant_user_type"] + break + + default: + break + } + } +} +``` + +Next, register the event handler delegate with the Rownd SDK: + +```swift +Rownd.addEventHandler(RowndEventHandler()) +``` + +Once the event handler is registered, it will receive events as they occur. The `RowndEvent` object contains the event type and any associated data. The event types are defined in the `RowndEventType` enum. + +#### List of events + +Here's a list of events that the Rownd SDK emits and the corresponding data that should be present in the event data dictionary. Remember to write your code defensively, as the data dictionary may be missing keys in some cases. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventTypePayload
User started signing in`.signInStarted` + ```javascript + { + method: "google" | "apple" | "phone" | "email" | "passkey" | etc; + } + ``` +
User signed in successfully`.signInCompleted` + ```javascript + { + method: "google" | "apple" | "phone" | "email" | "passkey" | etc, + user_type: "new_user" | "existing_user", + app_variant_user_type: "new_user" | "existing_user" | optional + } + ``` +
User sign in failed`.signInFailed` + ```javascript + { + reason: String; + } + ``` +
+ +### API reference + +In addition to the state observable APIs, Rownd provides imperative APIs that you can call to request sign in, get and retrieve user profile information, retrieve a current access token, or encrypt user data with the user's local key. + +#### `Rownd.requestSignIn() -> Void` + +Opens the Rownd sign-in dialog for authentication. + +#### `Rownd.requestSignIn(RowndSignInOptions(postSignInRedirect: "https://my-domain.com")) -> Void` + +#### `Rownd.requestSignIn(RowndSignInOptions(postSignInRedirect: "https://my-domain.com", intent: .signIn)) -> Void` + +Opens the Rownd sign-in dialog for authentication, as above. When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for `postSignInRedirect`. If this is a [Universal Link](https://developer.apple.com/ios/universal-links/), it will redirect the user back to your app. + +#### `Rownd.requestSignIn(with: RowndSignInHint) -> Void` + +#### `Rownd.requestSignIn(with: RowndSignInHint, signInOptions: RowndSignInOptions?) -> Void` + +Requests a sign-in, but with a specific authentication provider (e.g., Sign in with Apple). Rownd treats this information as a hint. If the specified authentication provider is enabled within your Rownd app configuration, it will be honored. If not, Rownd will fall back to the default flow. + +Supported values: + +* `.appleId` - Prompt user to sign in with their Apple ID +* `.google` - Prompt user to sign in with their Google account +* `.passkey` - Prompt user to sign in with a passkey if they've previously set one up +* `.guest` - Sign in the user anonymously as a guest. + +#### `RowndSignInOptions` + +Some of the `requestSignIn()` methods accept an optional `RowndSignInOptions` parameter. This class contains the following properties: + +* `postSignInRedirect: String?` (not recommended) - When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for `postSignInRedirect`. If this is a [Universal Link](https://developer.apple.com/ios/universal-links/), it will redirect the user back to your app. If you don't set this value, the user will be redirected to your app's subdomain as configured in the Rownd dashboard. + +* `intent: RowndSignInIntent?` - This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `.signIn` or `.signUp`. If you don't set this value, the user will be presented with the unified sign-in/sign-up flow. If you don't set this value, the user will be presented with the unified sign-in/sign-up flow. + +### `Rownd.signOut() -> Void` + +Clears the user's access token, removes the user's profile data, and returns the user to a completely unauthenticated state. + +### `Rownd.signOut(scope: RowndSignoutScope) -> Void` + +Revokes all tokens for the specified user causing them to be signed out on all devices. + +Supported values: + +* `.all` - All devices + +### `Rownd.getAccessToken(throwIfMissing: Bool = false) async throws -> String?` + +Assuming a user is signed-in, returns a valid access token, refreshing the current one if needed. + +By default, this function will return `nil` if an access token cannot be returned, either because the user is not signed in or because the refresh token is invalid. + +If an access token cannot be returned due to a temporary condition (e.g., inaccessible network), this function will throw an `AuthenticationError` indicating the failure reason (e.g., server or network error). + +You may also set `throwIfMissing` to `true` to force an error to be thrown if an access token cannot be returned. This will provide more granular reasons for the failure. The possible error cases for `AuthenticationError` are: + +- `.noAccessTokenPresent` - the user is not signed in +- `.invalidRefreshToken(details: String)` - the refresh token was invalid (e.g., the token was expired, revoked, or a previous exchange failed to complete successfully). The user will be signed out. +- `.networkConnectionFailure(details: String)` - a network condition prevented the token from being refreshed, even after several retries and should be re-attempted later +- `.serverError(details: String)` - an error occurred on the server and you should try again later + +Example: + +```swift + do { + let accessToken = try await Rownd.getAccessToken(throwIfMissing: true) + } catch { + switch error { + case AuthenticationError.noAccessTokenPresent: + // The user is not signed in + case AuthenticationError.invalidRefreshToken(let details): + // The refresh token was invalid. Request that the user sign in again. + case AuthenticationError.networkConnectionFailure(let details), + AuthenticationError.serverError(let details): + // Alert the user that they should try again due to some recoverable error + print("Server error occurred: \(details)") + } + } +``` + +#### Rownd.getAccessToken(\_ token: String) async -> String? + +When possible, exchanges a non-Rownd access token for a Rownd access token. This is primarily used in scenarios +where an app is migrating from some other authentication mechanism to Rownd. Using Rownd integrations, +the system will accept a third-party token. If it successfully validates, Rownd will sign-in the user and +return a fresh Rownd access token to the caller. + +This API returns `nil` if the token could not be validated and exchanged. If that occurs, it's likely +that the user should sign-in normally via `Rownd.requestSignIn()`. + +> NOTE: This API is typically used once. After a Rownd token is available, other tokens should be discarded. +> Example: + +```swift + // Assume `oldToken` was retrieved from some prior authenticator. + let accessToken = await Rownd.getAccessToken(oldToken) + if (accessToken != nil) { + // Navigate to the UI that a user should typically see + } else { + Rownd.requestSignIn() + } +``` + +#### Rownd.user.get() -> Dictionary\ + +Returns the entire user profile as a dictionary object + +#### Rownd.user.get\(field: String) -> T? + +Returns the value of a specific field in the user's data dictionary. You can use `user_id` to obtain the user's unique ID, which is always a string. + +Your application code is responsible for knowing which type the value should cast to. If the cast fails or the entry doesn't exist, a `nil` value will be returned. + +#### Rownd.user.set(data: Dictionary\) -> void + +Replaces the user's data with that contained in the dictionary. This may overwrite existing values, but must match the schema you defined within your Rownd application dashboard. + +Hint: use `AnyCodable.init(value)` to conform your values to the required type. + +#### Rownd.user.set(field: String, value: AnyCodable) -> void + +Sets a specific user profile field to the provided value, overwriting if a value already exists. If the field is flagged as `encrypted`, it will be encrypted on-device prior to storing in Rownd's platform. + +Hint: use `AnyCodable.init(value)` to conform your values to the required type. diff --git a/rownd-docusaurus/sdk-reference/mobile/overview.mdx b/rownd-docusaurus/sdk-reference/mobile/overview.mdx new file mode 100644 index 0000000..58738da --- /dev/null +++ b/rownd-docusaurus/sdk-reference/mobile/overview.mdx @@ -0,0 +1,113 @@ +--- +title: "Mobile SDK Overview" +sidebarTitle: Overview +--- + +## Rownd Mobile SDK Features +Rownd's Mobile SDKs deliver enterprise-grade authentication with native performance and delightful user experiences across iOS and Android platforms. + +### Deep Platform Integration + +Native integration with platform-specific features provides the best possible user experience: +- **iOS Integration**: + - Native Apple Sign-in + - Passkey/Face ID/Touch ID support + - Universal links for seamless deep linking + - SwiftUI and UIKit support +- **Android Integration**: + - Google One-Tap sign-in + - Native Passkey / Biometric authentication + - App links and deep linking + - Kotlin and Java support + +### Mobile-Optimized UI Components + +Pre-built, native UI elements that feel at home on each platform: +- **Native Bottom Sheets**: Platform-specific design and behavior +- **Adaptive Layouts**: Responsive to different screen sizes and orientations +- **Custom Animations**: Smooth, native-feeling transitions +- **Accessibility Support**: Built-in support for VoiceOver and TalkBack + +### No-Code Configuration + +Empower your team to make changes without app updates: +- **Dynamic Authentication Flow**: Modify sign-in methods and flows instantly +- **Visual Customization**: Update colors, text, and branding from the dashboard +- **Feature Flags**: Enable/disable features without code changes +- **A/B Testing**: Test different flows without deploying new versions + +### Automated User Journeys + +Create sophisticated onboarding experiences without code: +- **Trigger Controls**: Choose when and where to prompt users +- **Progressive Profiling**: Gradually collect user information +- **Conditional Flows**: Create different paths based on user attributes +- **Cross-Platform Consistency**: Maintain unified experiences across devices + +### Easy Implementation + +Quick integration process that respects developer workflows: +- **Comprehensive Documentation**: Clear setup guides and API references +- **Sample Applications**: Working examples for common use cases +- **Version Management**: Backward compatibility and clear upgrade paths +- **Technical Support**: Direct access to engineering support + + +## Steps for getting started: +1. [Set up your Rownd account](/welcome/getting-started) (only takes a minute). +2. Create an [app key](/configuration/app-credentials). +3. Install Rownd using an SDK. +4. [Configure customizations](/configuration/overview) and sign-in methods from the Rownd platform. + +## Rownd Mobile SDKs: + + + + Kotlin or Java + + + Swift + + } + href="/sdk-reference/mobile/flutter" + /> + + } + href="/sdk-reference/mobile/expo" + /> + diff --git a/rownd-docusaurus/sdk-reference/mobile/react-native.mdx b/rownd-docusaurus/sdk-reference/mobile/react-native.mdx new file mode 100644 index 0000000..0fceede --- /dev/null +++ b/rownd-docusaurus/sdk-reference/mobile/react-native.mdx @@ -0,0 +1,82 @@ +--- +title: "React Native" +description: "Rownd bindings for React Native" +icon: "react" +--- + +### Prerequisites + +You must be using React Native v0.64 or higher. + +### Installation + +First, install the Rownd SDK for React Native. + +```bash +npm install @rownd/react-native +``` + +### Expo + +You can find specific Expo installation instructions [here](/sdk-reference/mobile/expo). + +#### Android + +1. Ensure the Sdk versions match or are above provided versions. File: + _android/build.gradle_ + +```jsx +ext { + ... + minSdkVersion = 26 + compileSdkVersion = 32 + targetSdkVersion = 31 + ... +} +``` + +2. Install the Rownd library and dependencies. + +```bash +cd android && ./gradlew build +``` + +3. Check and update your ProGuard config using [the rules from our Android SDK](https://github.com/rownd/android/blob/main/README.md#proguard-config). + +4. Only required for Google Sign-in: Add a Rownd plugin initializer to your MainActivity file. File: *android/app/src/main/java/.../MainActivity.java + +```java +import android.os.Bundle; +import com.reactnativerowndplugin.RowndPluginPackage; + +public class MainActivity extends ReactActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + RowndPluginPackage.preInit(this); + } +} +``` + +#### iOS + +1. Ensure iOS version is at least 14\. File: _ios/Podfile_ + +```jsx +platform: ios, "14.0"; +``` + +2. Install the Rownd pod and it's dependencies + +```bash +cd ios && pod install +``` + +#### Enable deep linking + +Rownd supports automatically signing-in users when they initially install your +app or when they click a sign-in link when the app is already installed. + +Instructions for: [iOS](/configuration/mobile/ios) and [Android](/configuration/mobile/android) + + \ No newline at end of file diff --git a/rownd-docusaurus/sdk-reference/overview.mdx b/rownd-docusaurus/sdk-reference/overview.mdx new file mode 100644 index 0000000..685c9cb --- /dev/null +++ b/rownd-docusaurus/sdk-reference/overview.mdx @@ -0,0 +1,146 @@ +--- +title: "Rownd SDK Overview" +sidebarTitle: Overview +--- + +Whether you've got a website, blog, single-page app, traditional web app, or mobile app, Rownd has you covered. + +Rownd's SDKs have dozens of visual elements, including the sign-up and sign-in screens, automations, and the user-profile sections, which can save developers days of design and front-end work. + +Looking for an SDK you don't see? Reach out to us at support@rownd.io. Odds are we're already working on it. + +### Choose your applicaiton type + + + + Mobile app that runs on a device (Flutter, Swift, etc) + + + Webapp that runs in a browser (React, Next.js, etc) + + + A hosted or custom website (Wordpress, Webflow, etc) + + + Backend side of the app (Node.js, Django, etc) + + + + +## Jump directly to your SDK + +### Rownd Webapp / Website SDKs + + + + + + + + + +### Rownd Mobile SDKs + + + Kotlin or Java + + + Swift + + + + + +### Backend / Server-side SDKs + + + + + + + diff --git a/rownd-docusaurus/sdk-reference/web/angular.mdx b/rownd-docusaurus/sdk-reference/web/angular.mdx new file mode 100644 index 0000000..dda9e7c --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/angular.mdx @@ -0,0 +1,221 @@ +--- +title: "Angular" +description: Angular SDK reference +icon: angular +--- + +#### Installation + +Run `npm install @rownd/angular` or `yarn add @rownd/angular` + +### Usage + +The library provides an Angular Module and Service for dependency injection. + +In the main app.module.ts file, add the Rownd module. You'll also need to +include the `@ngrx/store` module as well, as Rownd will drive state updates +through it. + +```jsx +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { StoreModule } from '@ngrx/store'; +import { RowndModule, RowndService } from '@rownd/angular'; + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + StoreModule.forRoot({}), + RowndModule.forRoot({ appKey: '' }), + ], + providers: [], + bootstrap: [AppComponent], +}) +export class AppModule { + // Load the Rownd Service into your app + constructor(private rownd: RowndService) {} +} +``` + +#### Module params + +```jsx +import { Component } from '@angular/core'; +import { RowndService } from '@rownd/angular'; + +@Component({ + selector: 'protected-component', + templateUrl: 'protected.component.html', + styleUrls: ['protected.component.scss'], +}) +export class ProtectedComponent { + + constructor(private rownd: RowndService) { + // Subscribe to Rownd isAuthenticated observable + this.rownd.isAuthenticated$.subscribe({ + next(auth) { + console.log("is Authenticated: ", auth) + } + }); + + // Subscribe to Rownd User Data observable + this.rownd.user$.subscribe({ + next(user) { + console.log("user: ", user) + } + }); + } + + signIn() { + this.rownd.requestSignIn(); + } + + signOut() { + this.rownd.signOut(); + } +} +``` + +#### API Reference + +**requestSignIn()** + +Trigger the Rownd sign-in dialog. This accepts an optional parameter with +options to control the behavior of the sign in. See our +[SDK Docs](/sdk-reference/web/javascript--api-reference) +for a full list of supported options. + +```jsx +import { Component } from '@angular/core'; +import { RowndService } from '@rownd/angular'; + +@Component({ + selector: 'my-component', + template: ` + + `, +}) +export class MyComponent { + constructor(private rownd: RowndService) {} + + requestSignIn() { + this.rownd.requestSignIn({ + auto_sign_in: true, + identifier: '+19199998181', + post_login_redirect: '/dashboard' + }); + } +} +``` + +- `auto_sign_in`: boolean - when true, automatically trigger a sign-in attempt + if identifier is included or an email address or phone number has already been + set in the user data. + +- `identifier`: string - an email address or phone number (in E164 format) to + which a verification message may be sent. If the Rownd app is configured to + allow unverified users, then sign-in will complete without verification if the + user has not signed in previously. + +- `post_login_redirect`: string - at the conclusion of a successful sign in, + Rownd will redirect the user here. This can be a path on the current domain or + a full URL. + +**signOut()** + +Signs out the current user and clears their profile, returning them to a +completely unauthenticated state. + +```jsx +import { Component } from '@angular/core'; +import { RowndService } from '@rownd/angular'; + +@Component({ + selector: 'my-component', + template: ` + + `, +}) +export class MyComponent { + constructor(private rownd: RowndService) {} + + signOut() { + this.rownd.signOut() + } +} +``` + +**getAccessToken()** + +Get the current user's access token. + +```jsx +await this.rownd.getAccessToken({ waitForToken: true }); +``` + +- `waitForToken`: boolean - when true, if no access token is present or if it's + expired, the promise will not be resolved until a valid token is available. + While unlikely, this could result in waiting forever. + +**isAuthenticated$** + +An observable boolean that indicates whether the user is currently signed in. + +```jsx +import { Component } from '@angular/core'; +import { RowndService } from '@rownd/angular'; + +@Component({ + selector: 'my-component', + template: 'You're signed in! +}) +export class MyComponent { + constructor(private rownd: RowndService) { } +} +``` + +**user$** + +An observable object that represents information about the current user, +specifically their profile information. The schema will match whatever you +define in the Rownd Platform. See our +[documentation](https://docs.rownd.io/rownd/guides/configuration/user-profiles) +for more information on configuring this schema. + +```jsx +import { Component } from '@angular/core'; +import { RowndService } from '@rownd/angular'; + +Component({ + selector: 'my-component', + template: '
Hello, {{(this.rownd.user$ | async)?.first_name}}
+}) +export class MyComponent { + constructor(private rownd: RowndService) { } +} +``` + +**isInitializing$** + +An observable boolean that will be `true` until Rownd has fully loaded and +resolved the current user's authentication status. This usually takes only a few +milliseconds, but if you make decisions that depend on the `isAuthenticated$` +value while `isInitializing$` is still `true`, your code/logic may not work as +you expect. + +```jsx +import { Component } from '@angular/core'; +import { RowndService } from '@rownd/angular'; + +Component({ + selector: 'my-component' +}) +export class MyComponent { + constructor(private rownd: RowndService) { } + + // isInitializing$ is an observable + this.rownd.isInitializing$ +} +``` diff --git a/rownd-docusaurus/sdk-reference/web/django--python.mdx b/rownd-docusaurus/sdk-reference/web/django--python.mdx new file mode 100644 index 0000000..84af8f7 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/django--python.mdx @@ -0,0 +1,221 @@ +--- +title: "Django (Python)" +description: + "Integrate Rownd instant accounts and authentication into your Django-backed + project." +icon: python +--- + +### Installation + +Install via pip: + +```bash +pip install rownd-django +``` + +Or, add the `rownd-django` package to your dependencies. In `requirements.txt`, +this would look like: + +```txt +rownd-django>=1.0.0 +``` + + + This plugin only works with Django v3 and above. We strongly recommend + upgrading if you're using something older. If you can't for some reason, + please [get in + touch](mailto:support@rownd.io?subject=Django%soSDK:%20Request%20for%20older%20version%20support). + + +Next, add the Rownd app and authentication backend to your Django `settings.py` +file. + +```py +INSTALLED_APPS = [ + ... + 'rownd_django', +] + +AUTHENTICATION_BACKENDS = [ + 'rownd_django.auth.backend.RowndAuthenticationBackend', + 'django.contrib.auth.backends.ModelBackend' +] +``` + +If you're using Django REST Framework, then add the Rownd authentication class +to your `REST_FRAMEWORK` settings. + +```py +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rownd_django.auth.backend.RowndApiAuthentication', + ] +} +``` + +Finally, add your Rownd app credentials to your Django `settings.py` file. You +can obtain these from the [Rownd dashboard](https://app.rownd.io). These +credentials enable the Rownd authentication backend to communicate with the +Rownd API. + +```py +ROWND = { + 'APP_KEY': '', + 'APP_SECRET': '', +} +``` + +#### A note on Google Sign-in +If you plan to use Google sign-in, you'll need to add or update one last configuration item in your +`settings.py` while developing locally without HTTPS connections enabled. Without this setting, the +Google One Tap iframe will not load correctly due to a missing Referrer header. + +``` + SECURE_REFERRER_POLICY = "no-referrer-when-downgrade" +``` + +#### Configure the Rownd Hub (required) + +Rownd authentication requires a small code snippet to be embedded within your +app, present on all HTML pages. Setup for the Hub/snippet itself is outside the +scope of this document, but you can find the relevant setup guides for either +[single page apps](https://docs.rownd.io/rownd/sdk-reference/web/react-next.js) +or +[traditional web apps via vanilla js](https://docs.rownd.io/rownd/sdk-reference/web/javascript-browser). + +Use our SDKs to embed the Hub/snippet in your SPA or use the vanilla JS SDK to +add the snippet in your main Django template HTML. + +Now that everything is set up, you can add Rownd authentication to your APIs or +views. + +### Usage + +The Rownd Django SDK provides support for both "traditional" Django apps where +you have an authentication session that follows a user across page loads, as +well as "single-page" (SPA) Django apps using frameworks like React, Vue, etc. + +#### Single-page apps (SPA) / API-based + +When using an SPA framework like React, Vue, or similar, you'll likely want to +leverage the specific Rownd SDK for those frameworks. You can find a list of +supported frameworks in +[our documentation](https://docs.rownd.io/rownd/sdk-reference/web). + +Typically, an SPA will use an API-driven request/response flow which makes +typical sessions unnecessary (though Rownd supports them if you need them). We +highly recommend the +[Django REST framework](https://www.django-rest-framework.org/) for this +purpose. Rownd provides plug-and-play support for the REST framework's +authentication API. + +Here's an example of how you might configure an API to leverage Rownd's +authenticator, given the installation instructions above: + +```py +from rownd_django.auth.backend import RowndApiAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView + +class ExampleView(APIView): + authentication_classes = [RowndApiAuthentication] + permission_classes = [IsAuthenticated] + + def get(self, request, format=None): + content = { + 'user': str(request.user), # `django.contrib.auth.User` instance. + 'auth': str(request.auth), # None + } + return Response(content) +``` + +#### Traditional (non-SPA) apps / session-based + +In this flow, once a user has been authenticated with the Rownd Hub, the Hub +will make a request to your app's backend to set up a session for the user. + +First, ensure your project has session middleware enabled. + +```py +MIDDLEWARE = [ + ... + 'django.contrib.sessions.middleware.SessionMiddleware', + ... +] +``` + +Next, include the Rownd `session_authenticator` in your `urls.py` file. + +```py +urlpatterns = [ + ... + path('rownd/', include('rownd_django.auth.urls', namespace='rownd')), + ... +] +``` + +Finally, update your Rownd Hub code snippet to fire post-authenticate and post-sign-out API requests + to the session authenticator we just enabled. + +```js + + +``` + +The session authenticator will establish an authenticated session if one doesn't +already exist and will return a response indicating that the Rownd Hub should +trigger a page refresh. This is usually necessary for your app views to display +the desired authenticated context. In the event that an authenticated session +already exists, the Hub will not trigger further page refreshes. + +#### CSRF Protection +By default CSRF protection is disabled on the two sign-in and sign-out routes provided by Rownd. If +you would like to enable it on those endpoints, you must ensure all of your sites views contain the +`csrftoken` cookie and update your settings to enable the CSRF protection. You can find more information +on the `csrftoken` cookie [here](https://docs.djangoproject.com/en/4.2/ref/csrf/). +```python +ROWND = { + 'APP_KEY': '', + 'APP_SECRET': '', + 'CSRF_PROTECT_ROUTES': True +} +``` + diff --git a/rownd-docusaurus/sdk-reference/web/go.mdx b/rownd-docusaurus/sdk-reference/web/go.mdx new file mode 100644 index 0000000..0e87d04 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/go.mdx @@ -0,0 +1,637 @@ +--- +title: "Go" +sidebarTitle: "Go" +icon: golang +--- + +A comprehensive Go SDK for integrating Rownd authentication, user management, and group management into your applications. + +## Installation + +```bash +go get github.com/rownd/client-go/pkg/rownd +``` + +## Features + +- Token validation and management with EdDSA support +- User authentication and profile management +- Group management with member roles and invites +- HTTP middleware for authentication +- Comprehensive error handling +- Configurable caching for JWKs and WKC + +## Quick start + +```go +package main + +import ( + "context" + "log" + "github.com/rownd/client-go/pkg/rownd" +) + +func main() { + // Initialize client with options + client, err := rownd.NewClient( + rownd.WithAppKey("YOUR_APP_KEY"), + rownd.WithAppSecret("YOUR_APP_SECRET"), + rownd.WithBaseURL("https://api.rownd.io"), + ) + if err != nil { + log.Fatal(err) + } + + ctx := context.Background() + + // Create or update a user + user, err := client.Users.CreateOrUpdate(ctx, rownd.CreateOrUpdateUserRequest{ + Data: map[string]interface{}{ + "email": "user@example.com", + "first_name": "John", + "last_name": "Doe", + }, + }) + if err != nil { + log.Fatal(err) + } + log.Printf("User ID: %s", user.GetID()) +} +``` + +## Quick start with examples + +### Creating users + +```go +// Let Rownd generate an ID +user, err := client.Users.CreateOrUpdate(ctx, rownd.CreateOrUpdateUserRequest{ + UserID: "__default__", // Special value that tells Rownd to generate a user ID. Can be `__rowndid__`, `__uuid__`, `__objectid__`, or `__default__` for your app's configured default behavior. + Data: map[string]interface{}{ + "email": "user@example.com", + "first_name": "John", + "last_name": "Doe", + }, +}) +// Response: +// user = { +// ID: "user_a7b53gwdaml5jt7t71442nt7", +// State: "enabled", +// AuthLevel: "unverified", +// Data: { +// "email": "user@example.com", +// "first_name": "John", +// "last_name": "Doe", +// "user_id": "user_a7b53gwdaml5jt7t71442nt7" +// } +// } + +// Use your own ID +user, err := client.Users.CreateOrUpdate(ctx, rownd.CreateOrUpdateUserRequest{ + UserID: "custom_id_12345", + Data: map[string]interface{}{ + "email": "user@example.com", + }, +}) +``` + +### Searching for users + +```go +// Lookup by email +users, err := client.Users.List(ctx, rownd.ListUsersRequest{ + Fields: []string{"email", "first_name", "last_name", "user_id"}, // Specify fields to return + LookupFilter: []string{"user@example.com"}, +}) +// Response: +// users = { +// TotalResults: 1, +// Results: [{ +// ID: "user_a7b53gwdaml5jt7t71442nt7", +// State: "enabled", +// AuthLevel: "verified", +// Data: { +// "email": "user@example.com", +// "first_name": "John", +// "last_name": "Doe" +// }, +// VerifiedData: { +// "email": "user@example.com" +// } +// }] +// } + +// Pagination example +users, err := client.Users.List(ctx, rownd.ListUsersRequest{ + PageSize: ToPtr(10), // Get 10 results per page + After: ToPtr("user_lastid"), // Start after this user ID +}) +``` + +### Group management examples + +```go +// Create a group +group, err := client.Groups.Create(ctx, rownd.CreateGroupRequest{ + Name: "Engineering Team", + AdmissionPolicy: rownd.AdmissionPolicyInviteOnly, + Meta: map[string]any{ + "department": "Engineering", + "cost_center": "ENG-123", + }, +}) +// Response: +// group = { +// ID: "group_a3l1n2lsnb3q0xbul9enjnh7", +// Name: "Engineering Team", +// AdmissionPolicy: "invite_only", +// Meta: { +// "department": "Engineering", +// "cost_center": "ENG-123" +// }, +// CreatedAt: "2024-03-01T12:00:00Z", +// UpdatedAt: "2024-03-01T12:00:00Z" +// } + +// Create an invite +invite, err := client.GroupInvites.Create(ctx, rownd.CreateGroupInviteRequest{ + GroupID: group.ID, + Email: "new@example.com", + Roles: []string{"member"}, + RedirectURL: "/welcome", +}) +// Response: +// invite = { +// Link: "https://app.rownd.io/invite/abc123...", +// Invitation: { +// ID: "invite_xyz789", +// GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7", +// Email: "new@example.com", +// Roles: ["member"], +// State: "pending", +// CreatedAt: "2024-03-01T12:01:00Z" +// } +// } +``` + +### Token validation with claims + +```go +token, err := client.ValidateToken(ctx, "your-jwt-token") +// Response: +// token = { +// UserID: "user_a7b53gwdaml5jt7t71442nt7", +// AccessToken: "original-jwt-token", +// Claims: { +// Sub: "user_a7b53gwdaml5jt7t71442nt7", +// Iss: "https://api.rownd.io", +// Aud: ["app:app_xyz123"], +// Exp: 1709312400, +// Iat: 1709308800, +// AppUserID: "user_a7b53gwdaml5jt7t71442nt7", +// IsUserVerified: true, +// IsAnonymous: false, +// AuthLevel: "verified" +// } +// } +``` + +### Helpful utilities + +```go +// Convert values to pointers (useful for optional fields) +pageSize := rownd.ToPtr(10) +after := rownd.ToPtr("some_id") + +// Get value from pointer with fallback +value := rownd.ToValue(optionalPtr) // Returns actual value or zero value if nil + +// Extract token from context (in HTTP handlers) +token := rownd.TokenFromCtx(r.Context()) +if token != nil { + userID := token.UserID + authLevel := token.Claims.AuthLevel +} +``` + +## Authentication & token validation + +### Token validation +```go +// Validate a token +token, err := client.ValidateToken(ctx, "your-jwt-token") +if err != nil { + log.Fatal(err) +} + +// Access token claims +log.Printf("User ID: %s", token.UserID) +log.Printf("Auth Level: %s", token.Claims.AuthLevel) +``` + +### HTTP middleware +```go +import "github.com/rownd/client-go/pkg/rownd/middleware" + +// Create middleware handler +handler, err := rowndmiddleware.NewHandler(client, + rowndmiddleware.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + }), +) + +// Use middleware +router.Use(rowndmiddleware.WithAuthentication(handler)) +``` + +## User management + +### User operations (CRUD) +```go +// Get user +user, err := client.Users.Get(ctx, rownd.GetUserRequest{ + UserID: "user_id", +}) + +// List/lookup users +users, err := client.Users.List(ctx, rownd.ListUsersRequest{ + Fields: []string{"email", "first_name", "last_name"}, + LookupFilter: []string{"user@example.com"}, +}) + +// Delete user +err := client.Users.Delete(ctx, rownd.DeleteUserRequest{ + UserID: "user_id", +}) +``` + +## Group management + +### Groups +```go +// Create group +group, err := client.Groups.Create(ctx, rownd.CreateGroupRequest{ + Name: "Engineering Team", + AdmissionPolicy: rownd.AdmissionPolicyInviteOnly, + Meta: map[string]any{ + "department": "Engineering", + }, +}) + +// List groups +groups, err := client.Groups.List(ctx, rownd.ListGroupsRequest{}) + +// Delete group +err := client.Groups.Delete(ctx, rownd.DeleteGroupRequest{ + GroupID: "group_id", +}) +``` + +### Group invites +```go +// Create invite +invite, err := client.GroupInvites.Create(ctx, rownd.CreateGroupInviteRequest{ + GroupID: "group_id", + Email: "new@example.com", + Roles: []string{"member"}, + RedirectURL: "/welcome", +}) + +// List invites +invites, err := client.GroupInvites.List(ctx, rownd.ListGroupInvitesRequest{ + GroupID: "group_id", +}) + +// Delete invite +err := client.GroupInvites.Delete(ctx, rownd.DeleteGroupInviteRequest{ + GroupID: "group_id", + InviteID: "invite_id", +}) +``` + +## Group membership management + +### The difference between Group IDs and User IDs + +In Rownd's group system, there are two important identifiers: +- `user_id`: The unique identifier for a Rownd user (e.g., "user_a7b53gwdaml5jt7t71442ng7") +- `member_id`: The unique identifier for a user's membership in a specific group (e.g., "member_dnn5g4e3q5aptail2gr43kpj") + +A single user can be a member of multiple groups, with a different `member_id` for each group membership. + +```go +// Example group member structure +type GroupMember struct { + ID string `json:"id"` // This is the member_id + UserID string `json:"user_id"` // This is the user_id + Roles []string `json:"roles"` + State string `json:"state"` + Profile map[string]interface{} `json:"profile"` + GroupID string `json:"group_id"` +} +``` + +### Managing group members + +```go +// Add a user to a group +member, err := client.GroupMembers.Create(ctx, rownd.CreateGroupMemberRequest{ + GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7", + UserID: "user_a7b53gwdaml5jt7t71442nt7", + Roles: []string{"editor", "viewer"}, +}) +// Response: +// member = { +// ID: "member_dnn5g4e3q6aptail2gr43kpj", // The member_id +// UserID: "user_a7b53gwdaml5jt7t71442nt7", // The user_id +// Roles: ["editor", "viewer"], +// State: "active", +// Profile: { +// "email": "user@example.com", +// "first_name": "John" +// }, +// GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7" +// } + +// Update a member's roles using member_id +updatedMember, err := client.GroupMembers.Update(ctx, rownd.UpdateGroupMemberRequest{ + GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7", + MemberID: "member_dnn5g4e3q6aptail2gr43kpj", // Use member_id, not user_id + Roles: []string{"admin"}, +}) + +// List group members +members, err := client.GroupMembers.List(ctx, rownd.ListGroupMembersRequest{ + GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7", +}) +// Response: +// members = { +// TotalResults: 2, +// Results: [{ +// ID: "member_dnn5g4e3q6aptail2gr43kpj", +// UserID: "user_a7b53gwdaml5jt7t71442nt7", +// Roles: ["admin"], +// State: "active", +// Profile: { +// "email": "user@example.com" +// } +// }, { +// ID: "member_kll8h7g2p9qbxyzw4m5njth8", +// UserID: "user_b8c64hwdaml5kt8u82553ou8", +// Roles: ["viewer"], +// State: "active", +// Profile: { +// "email": "another@example.com" +// } +// }] +// } + +// Remove a member from a group using member_id +err := client.GroupMembers.Delete(ctx, rownd.DeleteGroupMemberRequest{ + GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7", + MemberID: "member_dnn5g4e3q6aptail2gr43kpj", // Use member_id, not user_id +}) +``` + +### Important notes about group membership + +1. **Member ID vs User ID** + - Use `member_id` when managing a specific membership (updating roles, removing from group) + - Use `user_id` when adding a new member to a group + - A user (`user_id`) can have multiple memberships (`member_id`s) across different groups + +2. **Group Ownership** + - Groups must always have at least one owner + - When removing the last owner, transfer ownership first + - Example of transferring ownership: + ```go + // Transfer ownership before removing the last owner + _, err = client.GroupMembers.Update(ctx, rownd.UpdateGroupMemberRequest{ + GroupID: "group_id", + MemberID: "new_owner_member_id", + Roles: []string{"owner", "member"}, + }) + ``` + +3. **Member States** + - `active`: Normal membership + - `suspended`: Temporarily restricted access + - `invited`: Pending acceptance of invitation + +4. **Common Role Types** + - `owner`: Full administrative control + - `admin`: Can manage members and content + - `editor`: Can modify content + - `viewer`: Read-only access + - Custom roles can be defined as needed + +## Group ownership and member management rules + +### Group ownership rules + +1. **Automatic owner assignment** + - The first member added to a group automatically receives the "owner" role + - Example of first member creation: + ```go + // First member automatically becomes owner + member, err := client.GroupMembers.Create(ctx, rownd.CreateGroupMemberRequest{ + GroupID: "group_id", + UserID: "user_id", + Roles: []string{"member"}, // "owner" will be automatically added + }) + // Response: + // member = { + // ID: "member_abc123", + // UserID: "user_id", + // Roles: ["owner", "member"], // Note: "owner" was automatically added + // State: "active" + // } + ``` + +2. **Owner requirements** + - Every group must maintain at least one owner at all times + - Attempting to remove the last owner will result in an error + ```go + // This will fail if it's the last owner + err := client.GroupMembers.Delete(ctx, rownd.DeleteGroupMemberRequest{ + GroupID: "group_id", + MemberID: "last_owner_member_id", // Will return error if last owner + }) + ``` + +3. **Group deletion requirements** + - A group must have at least one member. To remove all members, delete the group. + - Correct order of operations: + ```go + // Correct order: Delete group first, which removes all members + err := client.Groups.Delete(ctx, rownd.DeleteGroupRequest{ + GroupID: "group_id", + }) + + // Incorrect: Will fail if trying to remove last member while group exists + err := client.GroupMembers.Delete(ctx, rownd.DeleteGroupMemberRequest{ + GroupID: "group_id", + MemberID: "last_member_id", // Will return error + }) + ``` + +## Error handling + +The SDK provides structured error types for better error handling: + +```go +if err != nil { + switch e := err.(type) { + case *rownd.Error: + switch e.Kind { + case rownd.ErrAuthentication: + log.Printf("Authentication error: %v", e) + case rownd.ErrValidation: + log.Printf("Validation error: %v", e) + case rownd.ErrAPI: + log.Printf("API error: %v", e) + case rownd.ErrNetwork: + log.Printf("Network error: %v", e) + case rownd.ErrNotFound: + log.Printf("Not found error: %v", e) + } + case *rownd.MultiError: + log.Printf("Multiple errors occurred: %v", e) + default: + log.Printf("Unknown error: %v", err) + } +} +``` + +## Configuration options + +### Client options +```go +client, err := rownd.NewClient( + rownd.WithAppKey("key"), + rownd.WithAppSecret("secret"), + rownd.WithBaseURL("https://api.rownd.io"), + rownd.WithWKCCacheDuration(time.Hour), + rownd.WithJWKsCacheDuration(time.Hour), +) +``` + +### Request options +```go +client.Users.Get(ctx, request, + rownd.RequestWithHeader("X-Custom-Header", "value"), +) +``` + +## Testing + +Run all tests: +```bash +go test ./... +``` + +Run specific tests: +```bash +go test -v ./... -run TestRowndUsers +``` + +Run with timeout: +```bash +go test -v ./... -timeout 30s +``` + +## Types reference + +### Auth levels +```go +const ( + AuthLevelInstant AuthLevel = "instant" + AuthLevelUnverified AuthLevel = "unverified" + AuthLevelGuest AuthLevel = "guest" + AuthLevelVerified AuthLevel = "verified" +) +``` + +### Group admission policies +```go +const ( + AdmissionPolicyInviteOnly AdmissionPolicy = "invite_only" + AdmissionPolicyOpen AdmissionPolicy = "open" +) +``` + +## Environment setup + +### Using environment variables + +Create a `.env` file in your project root: + +```env +# .env +ROWND_APP_KEY=key_bd81v4usfn4c9wh6i83c13ak +ROWND_APP_SECRET=ras_32769e81.0.002bc537079f78d4bc890214fd85c63b313c0 +ROWND_APP_ID=app_xkbuml48qs3tyxxjjpaxeemv +ROWND_BASE_URL=https://api.rownd.io +``` + +Load environment variables in your code: + +```go +package main + +import ( + "github.com/joho/godotenv" + "github.com/rownd/client-go/pkg/rownd" + "log" + "os" +) + +func main() { + // Load .env file + if err := godotenv.Load(); err != nil { + log.Printf("Warning: .env file not found") + } + + // Initialize client with environment variables + client, err := rownd.NewClient( + rownd.WithAppKey(os.Getenv("ROWND_APP_KEY")), + rownd.WithAppSecret(os.Getenv("ROWND_APP_SECRET")), + rownd.WithBaseURL(os.Getenv("ROWND_BASE_URL")), + ) + if err != nil { + log.Fatal(err) + } +} +``` + +### Environment Files + +1. Add `.env` to your `.gitignore`: +```gitignore +# .gitignore +.env +``` + +2. For testing, create a separate `.env.test`: +```env +# .env.test +ROWND_TEST_APP_KEY=test_key_here +ROWND_TEST_APP_SECRET=test_secret_here +ROWND_TEST_APP_ID=test_app_id_here +ROWND_TEST_BASE_URL=https://api.rownd.io +``` + +3. Load different env files based on environment: +```go +func loadEnv() { + env := os.Getenv("GO_ENV") + if env == "test" { + godotenv.Load(".env.test") + } +} +``` + +## License + +This project is licensed under the MIT License - see the LICENSE file for details. diff --git a/rownd-docusaurus/sdk-reference/web/html.mdx b/rownd-docusaurus/sdk-reference/web/html.mdx new file mode 100644 index 0000000..889b230 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/html.mdx @@ -0,0 +1,144 @@ +--- +title: "HTML Hooks" +sidebarTitle: "HTML Hooks" +icon: code +--- + +## Installation + +Please reference one of Rownd's other [Web SDKs](/sdk-reference/web/overview) for instructions on installing Rownd onto your site or web app. The HTML Hooks functionality is available with any or our web SDKs. + +## HTML Hooks + +The Rownd Hub supports various hooks that can be used to modify the behavior of +content on a page. These are controlled by +[HTML data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use%5Fdata%5Fattributes). +The following attribute hooks are supported. + +## Sign in / sign up buttons / triggers + +### `data-rownd-sign-in-trigger` + +Attach to a clickable control (e.g., `` or ` +``` + +**`data-rownd-request-sign-in`** / **`data-rownd-require-sign-in`** + +When one of these attributes is present on any DOM element, the Rownd sign-in +modal will automatically display if the user is not currently signed in. + +The only difference between the two is that `data-rownd-request-sign-in` will +display a closable sign-in modal (i.e., with a close icon showing) whereas +`data-rownd-require-sign-in` will display a persistent, non-closable modal until +the user successfully completes the sign-in process. + +**Pre-set the user's email address or phone number** + +If you already know the current visitor's sign-in identifier (i.e., email or +phone), Rownd can pre-populate that into the sign-in modal. Simply add the +following additional attribute to the same element where the request/require +sign-in attribute is present: +`data-rownd-default-user-identifier="REPLACE_WITH_EMAIL_OR_PHONE"` + +Here's a complete example: + +```jsx +
+``` + +### Display user profile information for site customization + +Use these hooks when you want to customize site content with information about +the currently signed-in user. The fields available here will match those +specified in the Rownd dashboard. + +If the user's profile changes within the browser context, the changes will +automatically be reflected within the site. + +**`data-rownd-field-interpolate`** + +Replaces templated strings within the element's HTML content with the values +from the currently signed-in user's profile. + +Example: + +```jsx +

+ Hello, {{ first_name }} {{ last_name }}! +

+ +// Result:

Hello, Alice Remansi!

+``` + +**`data-rownd-field-mapping=""`** + +Examples: + +```jsx +

+ Hello, + + ! +

; + +Result:

+ {" "} + Hello, + Alice + Remansi! +

; +``` + +Rownd can also render images when this attribute is applied to an `img` element +and the field name corresponds to a field of type "image". Example: + +```jsx +

Profile Picture

+ +``` diff --git a/rownd-docusaurus/sdk-reference/web/javascript--api-reference.mdx b/rownd-docusaurus/sdk-reference/web/javascript--api-reference.mdx new file mode 100644 index 0000000..06160f0 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/javascript--api-reference.mdx @@ -0,0 +1,459 @@ +--- +title: "Javascript API Reference" +description: "API Reference for the Rownd Javascript API" +sidebarTitle: "API Reference" +--- + +## `requestSignIn(opts)` + +Show the Rownd sign-in dialog, or automatically initiate a sign-in. + +### Examples + +#### Prompt the user to sign in + +`requestSignIn()` can be called without any parameters and the user can choose to sign in +with any of your app's configured sign-in methods. + +```javascript +rownd.requestSignIn() +``` + +#### Automatically sign in a user using their email + +```javascript +rownd.requestSignIn({ + identifier: 'john.doe@acme.com', + auto_sign_in: true +}) +``` + +#### Prompt the user to sign in with Google and save a referral code to their user data +```javascript +rownd.requestSignIn({ + method: 'google', + user_data: { + referral_code: 'ref_123' + } +}) +``` + +### Parameters + + + An email address or phone number (in E164 format) to + which a verification message may be sent. If the Rownd app is configured to + allow unverified users, then sign-in will complete without verification if the + user has not signed in previously. + + This is frequently used in conjunction with + `auto_sign_in: true` to automatically sign in a specific user. + + + + ```javascript Email + rownd.requestSignIn({ identifier: 'john.doe@acme.com' }) + ``` + ```javascript Phone + rownd.requestSignIn({ identifier: '+19199999999' }) + ``` + + + + + When `true`, automatically trigger a sign-in + attempt _if_ `identifier` is included or an email address or phone number has + already been set in the user data. + + + + ```javascript Auto Sign-in + rownd.requestSignIn({ + identifier: 'john.doe@acme.com'. + auto_sign_in: true + }); + ``` + + + + + If set, Rownd will initiate a sign-in with the specified method. Must be one of + `'email'`, `'phone'`, `'google'`, `'one_tap'`, `'passkeys'`, `'crypto_wallet'`, or `'anonymous'` + + + + ```javascript Email + rownd.requestSignIn({ method: 'email' }); + ``` + ```javascript Phone + rownd.requestSignIn({ method: 'phone' }); + ``` + ```javascript Google + rownd.requestSignIn({ method: 'google' }); + ``` + ```javascript One Tap + rownd.requestSignIn({ + method: 'one_tap', + method_options: { + // This is optional. Let's you anchor the One Tap dialog to a specific + // spot on the page. + prompt_parent_id: '#one-tap-anchor-selector' + } + }); + ``` + ```javascript Passkeys + rownd.requestSignIn({ method: 'passkeys' }); + ``` + ```javascript Crypto Wallet + rownd.requestSignIn({ method: 'crypto_wallet' }); + ``` + ```javascript Anonymous + rownd.requestSignIn({ method: 'anonymous' }); + ``` + + + + + After the sign-in completes, Rownd will redirect to the configured `postLoginRedirectUrl` + or `postRegistrationUrl`. If `false`, the user will stay on the verification page. This + can be helpful if your site or application cannnot be reached via a traditional redirect, + such as if it's running in an iframe. + + + + ```javascript Disable Redirect + rownd.requestSignIn({ + method: 'email', + redirect: false, + }) + ``` + + + + + An absolute or relative URL for which to redirect the user after the sign-in completes. + + This overrides `postLoginRedirectUrl` and `postRegistrationUrl` if they are set. + + + + ```javascript Absolute URL + rownd.requestSignIn({ post_login_redirect: 'https:/my.site/signed_in' }) + ``` + ```javascript Relative Path + rownd.requestSignIn({ post_login_redirect: '/some/path?signed_in=true' }) + ``` + + + + + Extra user data to append to the user record when sign-in completes. + + + + ```javascript Referral Code + rownd.requestSignIn({ + user_data: { + referral_code: 'ref_123' + } + }) + ``` + + + + + When `true`, user data that was previously set using `rownd.user.set()` will be added to + the user record after sign-in. + + + + ```javascript No User Data + rownd.user.set({ nick_name: 'Joey' }) + + ... + + // { 'nick_name': 'joey' } will not be added to the user's data + rownd.user.requestSignIn({ + include_user_data: false + }) + ``` + + + + + This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `"sign_in"` or `"sign_up"`. If you don't set this value, the user will be presented with the unified sign-in/sign-up flow. + + + + ```javascript Sign Up + rownd.requestSignIn({ intent: 'sign_up' }) + ``` + + + + + The step in the sign-in dialog to display. Must be one of [LoginStep](#loginstep) + + This is an advanced option and rarely necessary for most use-cases + + + + ```javascript Success + rownd.requestSignIn({ + login_step: rownd.LoginStep.Success + }) + ``` + + + + +## `signOut()` + +Signs out the user, clearing their access token and user data + +```javascript +rownd.signOut() +``` + +## `getAccessToken()` + +Get the access token for the signed-in user. + +### Parameters + + + When `true`, if no access token is present or if + it's expired, the promise will not be resolved until a valid token is + available. While unlikely, this could result in waiting forever. + + + ```javascript + const token = await rownd.getAccessToken({ waitForToken: true }); + ``` + + + + +## `user` + + + Gets the data associated with the current user + + + ```javascript + // data = { user_id: "user_1235, email: "john.doe@acme.com", referral_code: "ref_123" } + const data = await rownd.user.get(); + ``` + + + + Replaces all of the user data for the current user. + + You can call `set()` prior to a user signing in. This can be useful to construct user data if your app + supports an unauthenticated state. + + + ```javascript + rownd.user.set({ email: "john.doe@acme.com", referral_code: "ref_123"}) + ``` + + + + + Sets a specific field in current user's data. + + + ```javascript + rownd.user.setValue('referral_code', 'ref_123') + ``` + + + + + Upload a file for a specific field + + The file parameter must be a javascript File. If the field name corresponds to + an image field, the mime type of the file must have an "image/" prefix (e.g. + "image/png") + + + ```javascript + rownd.user.uploadFile("profile_picture", file); + ``` + + + + + Show the user profile dialog + + + ```javascript + rownd.user.manageAccount() + ``` + + + + + + + + + + + + + + + + +## `auth` + + + Returns `true` if the current user is a verified user. In practice, this means that they have at least + one piece of verified data (email, phone, etc). + + + ```javascript + if (rownd.auth.isVerifiedUser()) { + console.log('verified!') + } + ``` + + + +## `requestFields()` + +Prompt the user to enter values to save in their data. You can specify the fields, submit button content, and the +queustion/prompt. + +### Examples + +#### Prompt the user to enter their first and last name + +```javascript +rownd.requestFields({ + fields: ['first_name', 'last_name'], + buttonText: 'Save name', + questionText: 'What\'s your name?' +}); +``` + + + + + + + + + + + + + +### Parameters + + + List of the field names for which to prompt the user. + + The fields must exist in your application's Data Types in order to save the data to the user's profile + + + + The text to show on the submit button + + + + The prompt or question displayed on the dialog + + +## `near` + + + The `near` API allows you to interact with the Rownd's [NEAR integration](/configuration/web3/near-overview). + + + Creates an implicit NEAR account for the current user if one doesn't already exist + + + ```javascript + const accountId = rownd.near.ensureImplicitAccount() + ``` + + + + + Prompts the user to create a named NEAR account + + ```javascript + const accountId = rownd.near.createNamedAccount() + ``` + + + + + + + + + + + + + + + + + Prompts the user to connect a NEAR accuont + + ```javascript + rownd.near.connectAccount() + ``` + + + + + + + + + + + + + + + + + Opens a dialog showing the details of the user's implicit NEAR account + + + ```javascript + const accountId = rownd.near.walletDetails() + ``` + + + + + + + + + + + + + + + + + +## `LoginStep` + +A step in the Rownd sign-in dialog. Used when calling [requestSignIn](#requestsignin) to show +a specific step. + + + + + + diff --git a/rownd-docusaurus/sdk-reference/web/javascript--browser.mdx b/rownd-docusaurus/sdk-reference/web/javascript--browser.mdx new file mode 100644 index 0000000..3b7be3d --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/javascript--browser.mdx @@ -0,0 +1,305 @@ +--- +title: "JavaScript" +--- + +The Rownd SDK for JavaScript enables seamless user authentication and profile management directly in the browser. This client-side SDK allows you to: +- Authenticate users without requiring a backend server +- Securely store and manage user profile information +- Customize the authentication flow to match your needs +- Handle user sessions and access tokens automatically +- Do it all with a simple, easy-to-implement code snippet + +## Getting started + +1. Get the Rownd Javascript code-snippet from the + [Rownd dashboard](https://app.rownd.io). + + ```jsx + // EXAMPLE ONLY--THIS WON'T WORK IN A REAL APP + + ``` + +2. Add the snippet to your website. If you're using a CMS (e.g., WordPress, + Webflow, Wix, etc.), you can typically add the snippet through the + "settings" portion of their editors. + + If you're testing locally or want to add the snippet directly to your site code, + add the snippet to your main layout or template HTML file. Ideally, add the snippet + just before the closing `` tag. + +### Deploying the Snippet to hosted websites + +After copying the code snippet, you'll need to add it to your website(s). Most +website builder software or content management systems (CMS) have an option to +embed "custom HTML" or "custom code" in your site's pages. We usually recommend +placing the snippet just before the closing `` tag. + +Here are links to instructions for a few popular hosting providers. See our +[JavaScript SDK reference](/sdk-reference/web/javascript--browser) for more details. + +- [Netlify](https://docs.netlify.com/site-deploys/post-processing/snippet-injection/) +- [Squarespace](https://support.squarespace.com/hc/en-us/articles/205815908) +- [Webflow](https://university.webflow.com/lesson/custom-code-in-the-head-and-body-tags) +- [Weebly](https://www.weebly.com/app/help/us/en/topics/descriptions-and-keywords)​ (see the section on "footer code") +- [Wix](https://support.wix.com/en/article/wix-editor-about-embeds-and-codes-on-your-site#embed-custom-code) +- [WordPress](sdk-reference/web/wordpress---woocommerce) + +At this point, if you load your site in a browser after saving or publishing, +you should see the Rownd Hub appear in the lower left-hand corner of the site. + +If you're building a single-page app in React, Vue, etc, then use our +framework-specific [SDKs](https://docs.rownd.io/sdk-reference/web/overview) instead of these instructions. + +If your single-page app is separate from your website, then you'll want to use +the instructions on this page for the website and the framework SDK instructions +for the single-page app. + +If you find any of this unclear, get in touch with us and we can help you figure +out which pieces you'll need. + +## Advanced +The following sections require some level of development knowledge + +### Configuring Rownd Behavior + +The behavior of Rownd and Rownd's UI components is configurable by appending configuration parameters to the global `_rphConfig` object. + +To set a config parameter, add an additional script block _after_ the main Rownd snippet. The important thing to see here is the call to `_rphConfig.push()`. + +```jsx + +``` + +**Configuration Parameters** + +#### setAppKey + + + +This is usually part of the snippet obtained from the Rownd dashboard, so you don't need to set it here. + +```jsx Example +_rphConfig.push(["setAppKey", "82f7fa9a-8110-416c-8cc8-e3c0506fbf93"]); +``` + +#### setPostLoginRedirect + + + +```jsx Example +_rphConfig.push(["setPostLoginRedirect", "https://app.rownd.io"]); +``` + +#### setPostRegistrationRedirect + + + +```jsx Example +_rphConfig.push(["setPostRegistrationRedirect", "https://app.rownd.io/post-registration"]); +``` + +#### setPostAuthenticationApi + + + +```jsx Example +_rphConfig.push(["setPostAuthenticationApi", + { + method: "post", + url: "https://api.acme.com/authenticate", + extra_headers: { + extra: "value" + }, + timeout: 3000 // 3s + } +]); +``` + +#### setPostSignOutApi + + + +```jsx Example +_rphConfig.push(["setPostSignOutApi", + { + method: "post", + url: "https://api.acme.com/sign-out", + extra_headers: { + extra: "value" + }, + } +]); +``` + +#### setPostSignOutCallback + + + +```jsx Example +_rphConfig.push(["setPostSignOutCallback", function () { + console.log('User signed out') +}]); +``` + +#### setPostUserDataUpdateApi + + + +```jsx Example +_rphConfig.push(["setPostUserDataUpdateApi", + { + method: "post", + url: "https://api.acme.com/user_data_update", + extra_headers: { + extra: "value" + }, + } +]); +``` + +#### setRootOrigin + + + +```jsx Example +_rphConfig.push(["setRootOrigin", "https://acme.com"]); +``` + +#### setLogLevel + + + +```jsx Example +_rphConfig.push(["setRootOrigin", "trace"]); +``` + +### Programmatic API + +In addition to the declarative markup described above, you can use the Rownd +Hub's programmatic API to create more advanced functionality. + +#### The \`rownd\` object + +Once the Rownd Hub initializes, it will place a `rownd` property on the global +`Window` object. All JS APIs are available on this object. Check out the JavaScript API reference [documentation](/sdk-reference/web/javascript--api-reference) for a comprehensive view of the API. + + +Before calling methods or accessing data on the Rownd API, you'll need to wait +for the API to be ready. Start by adding a function to the configuration's +`onLoaded` event, like this: + +You can interact with the Rownd JS Api + +```jsx + +``` + + +### Events + +The Rownd Hub emits various events when state changes occur. For example, +initial authentication, updates to user data, etc. You can listen for these +event changes and react to them. + + +#### `sign_in_completed` + +This event fires when a user has completed the sign in process. + + +The method used to sign in. Can be one of `"google"`, `"apple"`, `"phone"`, `"email"`, `"passkey"`, or `"anonymous"`. + + +The type of user that signed in. Can be either `"new_user"` or `"existing_user"`. + + +The type of user that signed in for the current app variant. Can be either `"new_user"` or `"existing_user"`. +`app_variant_user_type` will be released in early 2025 + + + + + ```javascript Example + rownd.events.addEventListener("sign_in_completed", (evt) => { + const { method, user_type, app_variant_user_type } = evt.detail; + }); + ``` + + +#### `sign_in_failed` + +This event fires when a user's sign in attempt fails. + + +The reason the sign in failed. + + + + ```javascript Example + rownd.events.addEventListener("sign_in_failed", (evt) => { + const { reason } = evt.detail; + console.log("Sign in failed:", reason); + }); + ``` + + +#### `auth` +This event fires any time the user moves from an unauthenticated state to an authenticated state. It will also fire any time the access token is refreshed. + + +The user's access token that can be used to authenticate API requests. + + +The unique identifier for the authenticated user. + + +The ID of the Rownd application. + + + + ```javascript Example + rownd.events.addEventListener("auth", (evt) => { + const { access_token, user_id, app_id } = evt.detail; + }); + ``` + + +#### `sign_out` +This event fires whenever a user is signed out. + + + ```javascript Example + rownd.events.addEventListener('sign_out', () => { + // do something now that the user has signed out + }); + ``` + + +#### `user_data` +This event fires any time a user's profile data changes. This could fire due to calls to `rownd.user.set()`, `rowns.user.setValue()`, changes to profile data in the Rownd Hub UI, or due to data changes when authenticating. + + +The user's updated profile data. + + + + ```javascript Example + rownd.events.addEventListener("user_data", (evt) => { + const { data } = evt.detail; + console.log("first_name:", data.first_name); + }); + ``` + + +### Hooks + +With the JavaScript SDK installed, you can use all of the HTML hooks described in the [HTML Hooks](/sdk-reference/web/html) documentation. diff --git a/rownd-docusaurus/sdk-reference/web/net-core.mdx b/rownd-docusaurus/sdk-reference/web/net-core.mdx new file mode 100644 index 0000000..b8b6ee9 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/net-core.mdx @@ -0,0 +1,171 @@ +--- +title: ".NET Core" +description: .NET Core SDK reference +icon: microsoft +--- + +Use this library to integrate Rownd into your .NET Core web application. + +Convenience wrappers are provided for the .NET Core Identity framework, but you +can also leverage token validation and + +### Installation + +From NuGet: + +```bash +dotnet add package Rownd --prerelease +``` + +### Supported versions + +- .NET 6.x + +- _Need a different version?_ + [Let us know!](https://github.com/rownd/dotnet/issues/new) + +### Usage + +#### Prepare configuration values + +The Rownd client requires an application key (which is publishable) and an +application secret (which should be kept private). If you don't have these +values, you can obtain them at https://app.rownd.io. + +Once you have them, you can add them to your `appsettings.json`: + +```json +{ + ... + "Rownd": { + "AppKey": "...", + "AppSecret": "..." + } +} +``` + +Or you can set environment variables and the library will use them automatically +(recommended): + +```json +export ROWND_APP_KEY="..." +export ROWND_APP_SECRET="..." +``` + +#### Inject Rownd into your application + +For the purposes of getting set up quickly, we'll assume you added the app key +and secret to your `appsettings.json` file as shown above. + +Next, add the following to your `Program.cs` file before the `builder.build()` +statement: + +```cs +using Rownd; + +... + +builder.Services.AddSingleton(sp => { + return new Rownd.Models.Config(builder.Configuration["Rownd:AppKey"], builder.Configuration["Rownd:AppSecret"]); +}); +builder.Services.AddSingleton(); +``` + +At this point, your server should accept Rownd JWTs and validate them. If you're +building a Single Page Application (SPA), you'll want to leverage our +framework-specific browser SDKs for ease of implementation. + +If you're building a more traditional web application, keep reading... + +#### Use Rownd with .NET Core Identity cookie-based sessions + +If you're adding Rownd to an existing application or building a new one that +uses the default, cookie-based session handling that comes with .NET Core +Identity, you'll need to add an additional controller to your app that will +accept a Rownd JWT and set a session cookie in response. + +Add a new controller that looks like this: + +```cs +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Rownd; +using Rownd.Helpers; + +namespace MyAppNamespace.Controllers +{ + [Route("/api/auth/rownd")] + public class RowndAuthController : RowndCookieExchange + { + // OPTIONAL + protected override async Task IsAllowedToSignIn(RowndUser rowndUser) { + // Run any custom logic here to ensure this user should be allowed to sign in. + + // return; // if everything is fine + + // throw new Exception("You aren't allowed here!"); // if you want to prevent the user from signing in + } + + public RowndAuthController(RowndClient client, ILogger logger, UserManager userManager) : base(client, logger) + { + _userManager = userManager; // If provided, Rownd will attempt to match the incoming user with an existing user in the database. + _addNewUsersToDatabase = true; // If you want Rownd to add new users to the database when they're first authenticated, set this to `true` (requires `_userManager`) + + _defaultAuthenticationScheme = IdentityConstants.ApplicationScheme; // Sets the authentication scheme (default: `IdentityConstants.ApplicationScheme`) + _signOutRedirectUrl = "/"; // Where to redirect the user after signing out (default: "/") + } + } +} +``` + +Let's examine what's happening in the above code: + +1. We're using the `RowndCookieExchange` base class to handle the exchange of + Rownd JWTs for a session cookie. It will accept a Rownd JWT in the POST + body, call the `HttpContext.SignInAsync()` method with the user's email + address and/or phone number and a role (if present). + +2. We're attaching a route to the controller (the base class is an abstract + `ApiController`) that we'll use later to handle the exchange of Rownd JWTs + for a session cookie. You can specify any route you like here, but + `/api/auth/rownd` is a decent choice. + +3. Using .NET dependency injection (DI), the server injects references to the + RowndClient and an ILogger (which are required). If you want Rownd to add + users to your database, then you'll also need to accept a reference to a + `UserManager` instance. + +4. `_addNewUsersToDatabase` is a protected, base class instance variable and is + set to `false` by default. If you want Rownd to add users to your database, + you'll need to set this to `true`. Likewise, `_userManager` is a protected, + base class instance variable and is set to `null` by default. Be sure to + populate this with the UserManager injected dependency if + `_addNewUsersToDatabase` is `true`. + +Finally, we need to install the Rownd Hub and instruct it to call our controller +API when the page loads. + +1. Follow + [these instructions](https://docs.rownd.io/rownd/sdk-reference/web/javascript-browser) + to install the Rownd Hub. You'll want to ensure it runs on every page of + your application, so be sure to add it as a common script or drop it + directly into your layout. + +2. Add the following script just below the Rownd Hub script: + + ```jsx + _rphConfig.push(['setPostAuthenticationApi', { + method: 'post', + url: '/api/auth/rownd' // Replace this with the route you specified in the controller + }]); + _rphConfig.push(['setPostSignOutApi', { + method: 'delete', + url: '/api/auth/rownd' // Replace this with the route you specified in the controller + }]); + ``` + +That's it! At this point, you should be able to fire up your app in a browser, +sign in with Rownd, and navigate around your app. + +If you run into issues, please +[let us know!](https://github.com/rownd/dotnet/issues/new) diff --git a/rownd-docusaurus/sdk-reference/web/nextjs.mdx b/rownd-docusaurus/sdk-reference/web/nextjs.mdx new file mode 100644 index 0000000..fbe9742 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/nextjs.mdx @@ -0,0 +1,721 @@ +--- +title: "Next.js" +description: "Integrate Rownd instant accounts and authentication into your Next.js project, including support for server-side rendering" +icon: n +--- + +## Quick Navigation + +| Section | Description | +|---------|-------------| +| [Installation](#installation) | How to install the Next.js SDK | +| [Basic Setup](#basic-setup) | Setting up providers and middleware | +| [Server-Side Features](#server-side-features) | Server components and authentication | +| [Client-Side Features](#client-side-features) | Client components and hooks | +| [Authentication Flow](#authentication-flow) | Complete auth implementation | +| [Protected Routes](#protected-routes) | Route protection strategies | +| [Data Access](#data-access) | Accessing user data (server/client) | +| [Best Practices](#best-practices) | Recommended patterns | +| [Type Definitions](#type-definitions) | TypeScript interfaces | +| [Examples](#examples) | Common use cases | + +## Installation + +```bash +npm install @rownd/next +# or +yarn add @rownd/next +``` + +## Basic Setup + +### 1. Provider Setup +In your root `layout.tsx`: + +```tsx +import { RowndProvider } from '@rownd/next'; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + {children} + + + + ); +} +``` + +### 2. Middleware Setup +In your `middleware.ts`: + +```typescript +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; +import { withRowndMiddleware } from '@rownd/next/server'; + +export const middleware = withRowndMiddleware((request: NextRequest) => { + return NextResponse.next(); +}); + +export const config = { + matcher: [ + // Required for Rownd token handling + '/api/rownd-token-callback', + // Add your protected routes + '/protected/:path*', + '/api/protected/:path*' + ] +}; +``` + +## Server-Side Features + +The `@rownd/next/server` package provides server-side authentication utilities: + +```typescript +import { + withRowndRequireSignIn, + getRowndUser, + getAccessToken, + isAuthenticated, + getRowndUserId, +} from '@rownd/next/server'; +import { cookies } from 'next/headers'; +``` + +### Server-Side Functions + +| Function | Description | Parameters | Return Type | Usage Example | +|----------|-------------|------------|-------------|---------------| +| `getRowndUser` | Retrieves the current authenticated user's data from Rownd | `cookies: ReadonlyRequestCookies` | `Promise` | `const user = await getRowndUser(cookies)` | +| `getRowndUserId` | Gets the current user's ID from server context | `cookies: ReadonlyRequestCookies` | `Promise` | `const userId = await getRowndUserId(cookies)` | +| `getRowndAccessToken` | Retrieves the current access token from server context | `cookies: ReadonlyRequestCookies` | `Promise` | `const token = await getRowndAccessToken(cookies)` | +| `isAuthenticated` | Checks if there is an authenticated user in server context | `cookies: ReadonlyRequestCookies` | `Promise` | `const isAuth = await isAuthenticated(cookies)` | +| `withRowndMiddleware` | Higher-order function for Next.js middleware to handle authentication | `middleware: NextMiddleware` | `NextMiddleware` | See middleware example below | +| `withRowndRequireSignIn` | Higher-order function to protect routes/pages/API handlers | `handler: Function, cookies: ReadonlyRequestCookies` | `Function` | See protected routes example below | + +### Example Usage + +```typescript +// Middleware setup +export const config = { + matcher: [ + '/api/rownd-token-callback', // Required for token handling + '/protected/:path*' // Your protected routes + ] +}; + +// Protected API route +async function handler(req: Request) { + const userId = await getRowndUserId(cookies); + const token = await getRowndAccessToken(cookies); + const user = await getRowndUser(cookies); + + if (!userId) { + return Response.json({ error: 'Not authenticated' }, { status: 401 }); + } + + return Response.json({ userId, user }); +} + +export const GET = withRowndRequireSignIn(handler, cookies); +``` + +## Client-Side Features + +The client-side features mirror the React SDK functionality but must be used within client components: + +### The useRownd Hook + +The `useRownd` hook provides comprehensive authentication and user management functionality: + +#### State Properties + +| Property | Type | Description | Example Usage | +|----------|------|-------------|---------------| +| `is_initializing` | `boolean` | Whether Rownd is still loading | `if (is_initializing) return ` | +| `is_authenticated` | `boolean` | Whether user is currently signed in | `if (is_authenticated) showDashboard()` | +| `access_token` | `string \| null` | Current JWT access token | `headers: { Authorization: Bearer ${access_token} }` | +| `user.data` | `Record` | User's profile data | `const { first_name, email } = user.data` || `user.groups` | `string[]` | Groups the user belongs to | `if (user.groups.includes('admin'))` | + +#### Authentication Methods + +| Method | Description | Parameters | Return Type | +|--------|-------------|------------|-------------| +| `requestSignIn()` | Triggers sign-in flow | `{ auto_sign_in?: boolean, identifier?: string, method?: string, post_login_redirect?: string }` | `void` | +| `signOut()` | Signs out current user | None | `void` | +| `getAccessToken()` | Gets current access token | `{ waitForToken?: boolean, timeoutMs?: number }` | `Promise` | + +#### User Data Methods + +| Method | Description | Parameters | Return Type | +|--------|-------------|------------|-------------| +| `setUser()` | Updates multiple user fields | `Record` | `Promise` | +| `setUserValue()` | Updates a single user field | `(field: string, value: any)` | `Promise` | +| `manageAccount()` | Opens account management UI | None | `void` | + +#### Additional Features + +| Feature | Description | Parameters | Return Type | +|---------|-------------|------------|-------------| +| `getFirebaseIdToken()` | Gets Firebase ID token | None | `Promise` | +| `getAppConfig()` | Gets app configuration | None | `Promise` | +| `passkeys` | Passkey authentication methods | `{ register: () => Promise, authenticate: () => Promise }` | Object | +| `events` | Event system for state changes | `addEventListener(event: string, callback: Function)` | EventEmitter | + +### Example Usage + +```tsx +'use client'; + +function ProfileManager() { + const { + is_authenticated, + is_initializing, + user, + setUser, + manageAccount, + getAccessToken + } = useRownd(); + + if (is_initializing) return
Loading...
; + if (!is_authenticated) return
Please sign in
; + + const updateProfile = async () => { + await setUser({ + first_name: 'John', + last_name: 'Doe' + }); + }; + + const fetchProtectedData = async () => { + const token = await getAccessToken({ waitForToken: true }); + // Use token for API calls + }; + + return ( +
+

Welcome {user.data.first_name}!

+ + +
+ ); +} +``` + +## Authentication Flow + +### Combined Server/Client Authentication + +```tsx +// app/profile/page.tsx +import { getRowndUser } from '@rownd/next/server'; +import { cookies } from 'next/headers'; +import { ClientProfile } from './client-profile'; + +// Server Component +export default async function ProfilePage() { + const serverUser = await getRowndUser(cookies); + + if (!serverUser) { + return
Please sign in
; + } + + // Initial data from server + return ( +
+

Server-rendered Profile

+
{JSON.stringify(serverUser.data, null, 2)}
+ + {/* Client component for real-time updates */} + +
+ ); +} + +// client-profile.tsx +'use client'; + +export function ClientProfile({ initialData }) { + const { user, is_initializing } = useRownd(); + + if (is_initializing) { + return
Syncing...
; + } + + return ( +
+

Real-time Profile Updates

+
{JSON.stringify(user.data, null, 2)}
+
+ ); +} +``` + +## Protected Routes + +### Server-Side Protection + +```typescript +// middleware.ts +import { withRowndMiddleware } from '@rownd/next/server'; + +export const middleware = withRowndMiddleware((request: NextRequest) => { + // Protect specific paths + if (request.nextUrl.pathname.startsWith('/protected')) { + // Additional custom logic + } + return NextResponse.next(); +}); +``` + +### Component-Level Protection + +```tsx +// Protected Server Component +import { withRowndRequireSignIn } from '@rownd/next/server'; +import { cookies } from 'next/headers'; + +async function ProtectedPage() { + const user = await getRowndUser(cookies); + return
Protected Content for {user.data.email}
; +} + +export default withRowndRequireSignIn(ProtectedPage, cookies); + +// Protected Client Component +'use client'; + +function ProtectedClientComponent() { + const { is_authenticated, is_initializing } = useRownd(); + + if (is_initializing) return
Loading...
; + if (!is_authenticated) return
Please sign in
; + + return
Protected Client Content
; +} +``` + +## Data Access + +### Server-Side Data Access + +```tsx +async function ServerComponent() { + const user = await getRowndUser(cookies); + const token = await getAccessToken(cookies); + + // Make authenticated API calls + const response = await fetch('https://api.example.com/data', { + headers: { + Authorization: `Bearer ${token}` + } + }); + + return
User: {user.data.email}
; +} +``` + +### Client-Side Data Access + +```tsx +'use client'; + +function ClientComponent() { + const { user, getAccessToken } = useRownd(); + + const fetchData = async () => { + const token = await getAccessToken(); + // Make authenticated API calls + }; + + return
User: {user.data.email}
; +} +``` + +## Best Practices + +1. **Server/Client Separation** + ```tsx + // Server Component + export default async function Page() { + const serverUser = await getRowndUser(cookies); + return ; + } + + // Client Component + 'use client'; + export function ClientComponent({ initialData }) { + const { user } = useRownd(); + // Use initialData for SSR, user for updates + } + ``` + +2. **Efficient Token Handling** + ```typescript + // Server-side + const token = await getAccessToken(cookies); + // Token includes app_id and user_id + + // Client-side + const { getAccessToken } = useRownd(); + const token = await getAccessToken(); + ``` + +3. **Error Boundaries** + ```tsx + 'use client'; + + class RowndErrorBoundary extends React.Component { + // Implementation + } + ``` + +## Type Definitions + +### Core Types + +| Type | Description | Interface | +|------|-------------|-----------| +| `RowndServerUser` | Server-side user type | `{ data: Record; access_token: string; app_id: string; user_id: string; }` | +| `RowndUser` | Client-side user type | `{ data: Record; groups: string[]; redacted_fields: string[]; verified_data: Record; meta: UserMeta; }` | +| `UserMeta` | User metadata | `{ created_at: string; updated_at: string; last_sign_in: string; }` | +| `SignInOptions` | Sign-in configuration | `{ auto_sign_in?: boolean; identifier?: string; method?: AuthMethod; post_login_redirect?: string; }` | +| `TokenOptions` | Token retrieval options | `{ waitForToken?: boolean; timeoutMs?: number; }` | +| `AuthMethod` | Authentication methods | `'email' \| 'phone' \| 'google' \| 'apple' \| 'passkey' \| 'anonymous'` | + +### Server-Side Types + +```typescript +// Server-side interfaces +interface RowndServerUser { + data: Record; + access_token: string; + app_id: string; + user_id: string; +} + +interface RowndServerConfig { + app_key: string; + api_url?: string; + hub_url_override?: string; +} + +type RowndMiddlewareConfig = { + matcher: string[]; +}; + +// Server utility types +type GetUserFn = (cookies: ReadonlyRequestCookies) => Promise; +type GetTokenFn = (cookies: ReadonlyRequestCookies) => Promise; +type IsAuthenticatedFn = (cookies: ReadonlyRequestCookies) => Promise; +``` + +### Client-Side Types + +```typescript +// Client-side interfaces +interface RowndUser { + data: Record; + groups: string[]; + redacted_fields: string[]; + verified_data: Record; + meta: { + created_at: string; + updated_at: string; + last_sign_in: string; + }; + is_loading: boolean; +} + +interface UseRowndReturn { + is_initializing: boolean; + is_authenticated: boolean; + user: RowndUser; + requestSignIn: (options?: SignInOptions) => void; + signOut: () => void; + getAccessToken: (options?: TokenOptions) => Promise; + setUser: (data: Record) => Promise; + setUserValue: (field: string, value: T) => Promise; + manageAccount: () => void; + getFirebaseIdToken: () => Promise; + getAppConfig: () => Promise; + passkeys: PasskeyMethods; + events: EventEmitter; +} +``` + +### TypeScript Examples + +#### Server-Side Example + +```typescript +// app/api/user/route.ts +import { + getRowndUser, + getRowndAccessToken, + withRowndRequireSignIn +} from '@rownd/next/server'; +import { cookies } from 'next/headers'; +import { NextResponse } from 'next/server'; + +interface UserPreferences { + theme: 'light' | 'dark'; + notifications: boolean; +} + +async function handler(req: Request) { + try { + const user = await getRowndUser(cookies); + const token = await getRowndAccessToken(cookies); + + if (!user) { + return NextResponse.json( + { error: 'Not authenticated' }, + { status: 401 } + ); + } + + // Type-safe user data access + const preferences: UserPreferences = { + theme: user.data.theme || 'light', + notifications: user.data.notifications ?? true + }; + + return NextResponse.json({ + user_id: user.user_id, + preferences, + token + }); + } catch (error) { + return NextResponse.json( + { error: 'Server error' }, + { status: 500 } + ); + } +} + +export const GET = withRowndRequireSignIn(handler, cookies); +``` + +#### Client-Side Example + +```typescript +// components/user-profile.tsx +'use client'; + +import { useRownd } from '@rownd/next'; +import { useState } from 'react'; + +interface ProfileFormData { + first_name: string; + last_name: string; + email: string; + preferences: { + theme: 'light' | 'dark'; + notifications: boolean; + }; +} + +interface ProfileProps { + initialData?: Partial; +} + +export function UserProfile({ initialData }: ProfileProps) { + const { + user, + is_authenticated, + is_initializing, + setUser, + getAccessToken + } = useRownd(); + + const [formData, setFormData] = useState({ + first_name: initialData?.first_name || '', + last_name: initialData?.last_name || '', + email: initialData?.email || '', + preferences: initialData?.preferences || { + theme: 'light', + notifications: true + } + }); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + try { + await setUser(formData); + const token = await getAccessToken({ waitForToken: true }); + + // Make authenticated API call + await fetch('/api/user/preferences', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData.preferences) + }); + } catch (error) { + console.error('Failed to update profile:', error); + } + }; + + if (is_initializing) { + return
Loading profile...
; + } + + if (!is_authenticated) { + return
Please sign in to view your profile
; + } + + return ( +
+
+ + setFormData(prev => ({ + ...prev, + first_name: e.target.value + }))} + /> +
+ +
+ + setFormData(prev => ({ + ...prev, + email: e.target.value + }))} + /> + {user.verified_data.email === formData.email && ( + ✓ Verified + )} +
+ +
+ +
+ + +
+ ); +} +``` + +#### Combined Server/Client Example + +```typescript +// app/profile/page.tsx +import { getRowndUser } from '@rownd/next/server'; +import { cookies } from 'next/headers'; +import { UserProfile } from '@/components/user-profile'; + +interface PageProps { + params: Record; + searchParams: Record; +} + +export default async function ProfilePage({ params, searchParams }: PageProps) { + const user = await getRowndUser(cookies); + + if (!user) { + return
Please sign in to view your profile
; + } + + // Pass server-fetched data to client component + return ( +
+

User Profile

+ +
+ ); +} +``` + +## Examples + +### Full Authentication Flow + +```tsx +// app/auth/page.tsx +import { getRowndUser } from '@rownd/next/server'; +import { cookies } from 'next/headers'; +import { AuthClient } from './auth-client'; + +export default async function AuthPage() { + const serverUser = await getRowndUser(cookies); + return ; +} + +// auth-client.tsx +'use client'; + +export function AuthClient({ initialUser }) { + const { + is_initializing, + is_authenticated, + user, + requestSignIn, + signOut + } = useRownd(); + + if (is_initializing) { + return
Loading...
; + } + + return ( +
+ {is_authenticated ? ( +
+

Welcome {user.data.first_name}!

+ +
+ ) : ( + + )} +
+ ); +} +``` + +For more examples and detailed client-side features, refer to the [React SDK documentation](/sdk-reference/web/react#examples). diff --git a/rownd-docusaurus/sdk-reference/web/node-js.mdx b/rownd-docusaurus/sdk-reference/web/node-js.mdx new file mode 100644 index 0000000..ff2c39c --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/node-js.mdx @@ -0,0 +1,198 @@ +--- +title: "Node.js" +description: NodeJS SDK reference +icon: node +--- + +Use this library to integrate Rownd into your Node.js application. Convenience +wrappers are provided for common server implementations. + +### Installation + +```bash +npm i @rownd/node +``` + +### Supported frameworks + +In addition to supporting Node.js generally, the SDK also provides direct support for the following frameworks: + +- [Express](#express) + +Don't see your framework of choice? Open an issue and request it, or contribute +it via pull request! + +### Usage + +### Vanilla JS (Node.js) + +The SDK exposes the following methods to help you validate user tokens, create or update user records, generate sign-in links, and so on. + +Here's a basic usage example: + +```js +const Rownd = require("@rownd/node"); + +const rownd = Rownd.createInstance({ + app_key: 'YOUR_ROWND_APP_KEY', + app_secret: 'YOUR_ROWND_APP_SECRET' +}); + +try { + // Receive a Rownd bearer token within your request headers (e.g., Authorization: Bearer ) + let token = headers['authorization'].replace(/^bearer /i, ''); + + let tokenInfo = await rownd.validateToken(token); + // Available properties: decoded_token, user_id, access_token (the same token you passed into `validateToken()`) + + // If you want to grab the user's profile from Rownd + let userInfo = await rownd.fetchUserInfo({ user_id: tokenInfo.user_id }); + + console.log(userInfo.data); // Print user profile to console +} catch (err) { + // Something went wrong--probably the token was invalid, expired, etc. +} + +``` + +#### Express + +An `authenticate` function is provided for use as Express middleware. It takes +the usual `req, res, next` arguments and will call `next()` if authentication +succeeds or `next(err)` if it fails. + +Upon successful authentication, the request will be augmented with a `tokenInfo` +property containing details about the authenticated token. `req.isAuthenticated` +will also be set to `true`. + +Each user's information is cached in memory for a short period of time to speed +up subsequent requests. + +See the Express example for a working implementation. + +Here's an example protecting one route: + +```js +const { rownd } = require("@rownd/node"); +const { authenticate } = rownd.express; + +app.get("/protected-route", authenticate(), (req, res) => { + res.send({ + message: "You are authenticated!", + tokenObj: req.tokenObj, + }); +}); +``` + +Here's an example protecting multiple routes on a certain path prefix: + +```js +const { rownd } = require("@rownd/node"); +const { authenticate } = rownd.express; +``` + +app.use('/protected-path', authenticate()); + +The `authenticate()` function accepts an optional `options` object containing +the following properties: + +- `fetchUserInfo: boolean (default: false)` \- If `true`, the user's data will + be fetched from the Rownd API and annotated on the request object as + `req.user`. When present, it will contain a set of key/value pairs that match + your application's schema. The user's data will be cached for a short period + of time to speed up subsequent requests. + +- `errOnInvalidToken: boolean (default: true)` \- When `true`, the an error will + be passed to `next(err)` if the token fails to validate. When `false`, the + token will still be validated, but `next()` will be called without an error. + `req.isAuthenticated` will be `false` and `req.tokenInfo` will be `null`. + +## API reference + +Most methods return a Promise that will resolve with the result of the call or will reject (throw) if an error occurs, so you should be prepared to handle any errors. + +### Rownd.createInstance(opts) + +Creates a new instance of the Rownd client. It requires the following object properties as a single argument: +- `app_key` - Your Rownd application key. +- `app_secret` - Your Rownd application secret. + +Optionally, you can also pass in the following properties: +- `timeout` - The number of milliseconds to wait before timing out a request. Defaults to 10 seconds. If you're on a slow network and see any "Request timed out" errors, try increasing this value. + +Example: + +```js +const rownd = Rownd.createInstance({ + app_key: 'YOUR_ROWND_APP_KEY', + app_secret: 'YOUR_ROWND_APP_SECRET' +}) +``` + +Once you have an instance, you can use it to call various Rownd APIs or leverage supported frameworks. + +### instance.express +Provides convenience handlers for the Express framework. See the usage section on Express for more information on how to use it. + +### `instance.validateToken(token: string): Promise` +Validates a Rownd bearer token. Returns a promise that resolves to a token validation payload. + +In many cases, you'll retrieve a token from your REST API's `Authorization` header. Be sure to strip off the `Bearer ` portion of the header and just pass the raw token to this method. + +If the validation is successful, the resulting object will look approximately like this: + +```js +{ + decoded_token: { + "jti": "345b7a0f-1ab4-482b-99e7-4466b1cac0ad", + "aud": [ + "app:290167281732813315", + ], + "sub": "rownd|61f3053251f2420069455976", + "iat": 1660056446, + "https://auth.rownd.io/app_user_id": "71f6ceeb-ee0a-4437-9b44-e6229defbab8", + "https://auth.rownd.io/is_verified_user": true, + "iss": "https://api.dev.rownd.io", + "exp": 1660060046 + }, + user_id: "71f6ceeb-ee0a-4437-9b44-e6229defbab8", + access_token: "eyJhbGciOiJ....EluFfu9Dg", +} +``` + +### `instance.fetchUserInfo(opts: TFetchUserInfoOpts): Promise` +Retrieves a user's profile from Rownd containing fields that match your Rownd application's schema. + +### `instance.createOrUpdateUser(user: TUser): Promise` +Creates or updates a user's profile in Rownd. The user object must contain an `id` property. If the user already exists, the existing profile will be updated. If the user does not exist, a new user/profile will be created. + +Example: + +```js +let user = await instance.createOrUpdateUser({ + id: '71f6ceeb-ee0a-4437-9b44-e6229defbab8', + data: { + first_name: 'Juliet', + email: 'juliet@rose.com' + } +}) +``` + +### `instance.deleteUser(userId: String): Promise` +Deletes a user and all associated data from Rownd. + +### `instance.createSignInLink(opts: CreateSignInLinkOpts): Promise` + +Creates a sign-in "magic" link that will automatically sign in a user based on their email address, phone number, etc when they click the link. + +Example: + +```js +let signInLink = await instance.createSignInLink({ + redirect_url: 'https://example.com/dashboard', + email: 'juliet@rose.com', + data: { + first_name: 'Juliet', + } +}); +``` diff --git a/rownd-docusaurus/sdk-reference/web/overview.mdx b/rownd-docusaurus/sdk-reference/web/overview.mdx new file mode 100644 index 0000000..6372311 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/overview.mdx @@ -0,0 +1,83 @@ +--- +title: "Web SDK Overview" +sidebarTitle: Overview +--- + +## Rownd Web SDK Features +Rownd's Web SDKs provide robust authentication solutions with seamless integration and exceptional user experiences across various web platforms. + +### Web-Optimized UI Components + +Pre-built, responsive UI elements that enhance user interaction: +- **Customizable Modals**: Easily match your brand's look and feel +- **Adaptive Layouts**: Responsive design for all screen sizes +- **Smooth Transitions**: Enhance user experience with native-feeling animations +- **Accessibility Features**: Built-in support for screen readers and keyboard navigation + +### No-Code Configuration + +Enable your team to make changes without redeploying: +- **Dynamic Authentication Flow**: Instantly modify sign-in methods and flows +- **Visual Customization**: Update styles and branding from the dashboard +- **Feature Toggles**: Enable/disable features without code changes +- **A/B Testing**: Experiment with different flows without redeploying + +### Automated User Journeys + +Create engaging onboarding experiences without code: +- **Trigger Controls**: Define when and where to prompt users +- **Progressive Profiling**: Collect user information over time +- **Conditional Flows**: Tailor experiences based on user attributes +- **Cross-Browser Consistency**: Ensure a unified experience across all browsers + +### Developer-Friendly Implementation + +Streamlined integration process that aligns with developer workflows: +- **Comprehensive Documentation**: Detailed setup guides and API references +- **Sample Projects**: Ready-to-use examples for common scenarios +- **Version Management**: Ensure compatibility with clear upgrade paths +- **Technical Support**: Access to expert engineering support + +## Steps for getting started: +1. [Set up your Rownd account](/welcome/getting-started) (only takes a minute). +2. Create an [app key](/configuration/app-credentials). +3. Install Rownd using an SDK. +4. [Configure customizations](/configuration/overview) and sign-in methods from the Rownd platform. + +## Rownd Web SDKs: + + + + Hooks and Components + + + Services and Directives + + + Components and Plugins + + + + Vanilla JS + + diff --git a/rownd-docusaurus/sdk-reference/web/react.mdx b/rownd-docusaurus/sdk-reference/web/react.mdx new file mode 100644 index 0000000..2210a41 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/react.mdx @@ -0,0 +1,1612 @@ +--- +title: "React" +description: React SDK reference +icon: react +--- + +## Quick Navigation + +| Section | Description | +|---------|-------------| +| [Installation](#installation) | How to install the React SDK | +| [Basic Setup](#usage) | Setting up the RowndProvider | +| [Authentication States](#authentication-states) | Four possible auth states and handling | +| [User Management](#user-object-structure) | Working with user data and profiles | +| [Sign In Options](#sign-in-request-options) | Customizing the sign-in experience | +| [HTML Hooks](#html-hooks-integration) | Using declarative data attributes | +| [Type Definitions](#type-definitions) | TypeScript interfaces and types | +| [Best Practices](#best-practices) | Recommended patterns and approaches | +| [Advanced Features](#advanced-features) | Advanced SDK capabilities | +| [API Integration](#type-safe-api-integration) | Making authenticated API calls | +| [Account Management](#account-management) | Managing user accounts | + +### Installation + +Simply run `npm install @rownd/react` or `yarn add @rownd/react`. + +### Usage + +The library provides a React provider and hook for the Rownd browser API. + +In your app's main entrypoint, add the Rownd provider, likely before other +providers: + +```jsx +import React from 'react', +import ReactDOM from 'react-dom'; +import { RowndProvider } from '@rownd/react'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +); +``` + + + The Rownd React SDK automatically injects the Rownd Hub snippet into your React application, so you should _not_ + manually include the Hub snippet in your HTML page. Doing so will produce unexpected results. + + + + Rownd has a number of built in features including `getAccessToken()` which will fetch your token. Rownd's SDK automatically checks the token and do token refreshes. Rownd takes care of the UI for your app as well. + + +### Provider Configuration + +The RowndProvider component accepts the following configuration options: + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| `appKey` | string | Yes | The application key generated in the Rownd dashboard. This uniquely identifies your application. | +| `postLoginRedirect` | string | No | URL where users will be redirected after successful sign-in. If not provided, users stay on the current page. | +| `postRegistrationRedirect` | string | No | URL where new users will be redirected after registration. Useful for onboarding flows. | +| `rootOrigin` | string | No | Root domain for multi-domain setups (e.g., "https://yourdomain.com"). Used when your app spans multiple subdomains. | + +### The useRownd Hook + +The `useRownd` hook is your primary interface for accessing authentication state and user data. It provides a comprehensive set of properties and methods: + +#### State Properties + +| Property | Type | Description | Usage Example | +|----------|------|-------------|---------------| +| `is_initializing` | boolean | Indicates if Rownd is still loading. Always check this before making auth-dependent decisions. | `if (is_initializing) return ` | +| `is_authenticated` | boolean | Whether the user is currently signed in. | `if (is_authenticated) showDashboard()` | +| `access_token` | string | The current JWT access token. Updates automatically when refreshed. | `headers: { Authorization: Bearer ${access_token} }` | +| `user.data` | object | The user's profile data. Contains all user fields. | `const { first_name, email } = user.data` | +| `user.is_loading` | boolean | Whether user data is being loaded/updated | `if (user.is_loading) showSpinner()` | + +#### Authentication Methods + +| Method | Description | Parameters | Return Type | +|--------|-------------|------------|-------------| +| `requestSignIn()` | Triggers the sign-in flow | `{ auto_sign_in?: boolean, identifier?: string, method?: string }` | `void` | +| `signOut()` | Signs out the current user | None | `void` | +| `getAccessToken()` | Gets the current access token | `{ waitForToken?: boolean }` | `Promise` | + +#### User Data Methods + +| Method | Description | Parameters | Return Type | +|--------|-------------|------------|-------------| +| `setUser()` | Updates multiple user fields | `Record` | `Promise` | +| `setUserValue()` | Updates a single user field | `(field: string, value: any)` | `Promise` | +| `manageAccount()` | Opens account management UI | None | `void` | + +#### User Object Structure + +The user object provides comprehensive information about the current user: + +| Property | Type | Description | +|----------|------|-------------| +| `user.data()` | object | User's profile data including custom fields | +| `user.data.{data-type}` | Varies | User's profile data including custom fields; for example; first_name| +| `user.groups` | string[] | Groups the user belongs to | + + +#### Example User Data Structure + +```typescript +// Example of user.data() return value +interface UserExample { + // Core user information + email: string; // "example@example.com" + first_name: string; // "First" + last_name: string; // "Example" + user_id: string; // "21245bc6-8a9a-4229-9c30-6b7adsd97c20" + + + // Custom fields + investor_type?: string; // "" + place_of_employment?: string; // "Rownd" + position?: string; // "Engineering" +} + +// Usage example +function UserProfileDisplay() { + const { user } = useRownd(); + const userData = user.get(); + + return ( +
+ {/* Core Information */} +

{userData.first_name} {userData.last_name}

+

Email: {userData.email}

+ + {/* Work Information */} + {userData.place_of_employment && ( +
+

Works at: {userData.place_of_employment}

+

Position: {userData.position}

+
+ )} + + {/* Authentication Info */} + {userData.google_id && ( +

Authenticated via Google

+ )} + + {/* Custom Fields */} + {userData.investor_type && ( +

Investor Type: {userData.investor_type}

+ )} + + {/* Technical Details */} + User ID: {userData.user_id} +
+ ); +} +``` + +Note: The actual fields available in `user.get()` will depend on your application's configuration in the Rownd dashboard. The example above shows common fields, but you can add custom fields as needed for your application. + +#### Authentication State + +The auth object provides detailed authentication information: + +| Property | Type | Description | +|----------|------|-------------| +| `auth.access_token` | string | Current JWT access token | +| `auth.app_id` | string | ID of the current application | +| `auth.is_authenticated` | boolean | Whether user is authenticated | +| `auth.is_verified_user` | boolean | Whether user has verified credentials | +| `auth.auth_level` | string | Current authentication level | + +#### Events API + +The SDK provides an event system to react to various state changes: + +```jsx +function EventExample() { + const { events } = useRownd(); + + useEffect(() => { + // Listen for authentication changes + events.addEventListener('auth', (event) => { + const { access_token, user_id, app_id } = event.detail; + console.log('User authenticated:', user_id); + }); + + // Listen for user data changes + events.addEventListener('user_data', (event) => { + const { data } = event.detail; + console.log('User data updated:', data); + }); + + // Listen for sign-in completion + events.addEventListener('sign_in_completed', (event) => { + const { method, user_type } = event.detail; + console.log(`Signed in with ${method} as ${user_type}`); + }); + + return () => { + // Clean up listeners + events.removeEventListener('auth'); + events.removeEventListener('user_data'); + events.removeEventListener('sign_in_completed'); + }; + }, [events]); + + return
Event Listener Example
; +} +``` + +#### App Configuration + +Access application configuration: + +```jsx +function AppConfigExample() { + const { getAppConfig } = useRownd(); + + useEffect(() => { + async function fetchConfig() { + const config = await getAppConfig(); + console.log('App config:', config); + } + fetchConfig(); + }, [getAppConfig]); + + return
App Config Example
; +} +``` + +#### Firebase Integration + +For applications using Firebase: + +```jsx +function FirebaseExample() { + const { getFirebaseIdToken } = useRownd(); + + const authenticateWithFirebase = async () => { + const firebaseToken = await getFirebaseIdToken(); + // Use token with Firebase Auth + console.log('Firebase token:', firebaseToken); + }; + + return ( + + ); +} +``` + +#### Passkey Authentication + +Complete passkey implementation: + +```jsx +function PasskeyAuthenticationExample() { + const { passkeys } = useRownd(); + + const handleRegistration = async () => { + try { + await passkeys.register(); + console.log('Passkey registered successfully'); + } catch (error) { + console.error('Passkey registration failed:', error); + } + }; + + const handleAuthentication = async () => { + try { + await passkeys.authenticate(); + console.log('Authenticated with passkey'); + } catch (error) { + console.error('Passkey authentication failed:', error); + } + }; + + return ( +
+

Passkey Authentication

+ + +
+ ); +} +``` + +#### Complete User Profile Management + +Example showing comprehensive user data management: + +```jsx +function UserProfileManager() { + const { + user, + setUser, + setUserValue, + manageAccount + } = useRownd(); + + const { + data, + groups, + verified_data, + is_loading, + redacted_fields + } = user; + + // Monitor loading state + if (is_loading) { + return
Loading user data...
; + } + + // Check for verified data + const hasVerifiedEmail = verified_data.email === data.email; + const hasVerifiedPhone = verified_data.phone_number === data.phone_number; + + return ( +
+

User Profile

+ + {/* Basic Information */} +
+

Basic Information

+
Name: {data.first_name} {data.last_name}
+
+ Email: {data.email} + {hasVerifiedEmail && (Verified)} +
+
+ Phone: {data.phone_number} + {hasVerifiedPhone && (Verified)} +
+
+ + {/* Group Membership */} +
+

Groups

+
    + {groups.map(group => ( +
  • {group}
  • + ))} +
+
+ + {/* Custom Data */} +
+

Custom Data

+
+          {JSON.stringify(data, null, 2)}
+        
+
+ + {/* Actions */} +
+

Actions

+ +
+
+ ); +} +``` + +### Type Definitions + +For TypeScript users, here are the comprehensive interfaces: + +```typescript +// User Types +interface RowndUser { + data: Record; + groups: string[]; + redacted_fields: string[]; + verified_data: Record; + meta: { + created_at: string; + updated_at: string; + last_sign_in: string; + }; + is_loading: boolean; + instant_user: { + is_initializing: boolean; + }; +} + +interface UserData { + first_name?: string; + last_name?: string; + email?: string; + phone_number?: string; + [key: string]: any; // Custom fields +} + +// Authentication Types +interface RowndAuth { + access_token: string | null; + app_id: string; + is_authenticated: boolean; + is_verified_user: boolean; + auth_level: 'high' | 'low' | 'none'; +} + +interface SignInOptions { + auto_sign_in?: boolean; + identifier?: string; + method?: 'email' | 'phone' | 'google' | 'apple' | 'passkey' | 'anonymous'; + post_login_redirect?: string; + user_data?: Record; + auto_submit?: boolean; +} + +interface TokenOptions { + waitForToken?: boolean; + timeoutMs?: number; +} + +// Event Types +interface RowndEvents { + addEventListener: (event: RowndEventType, callback: (event: CustomEvent) => void) => void; + removeEventListener: (event: RowndEventType) => void; +} + +type RowndEventType = + | 'auth' + | 'user_data' + | 'sign_in_started' + | 'sign_in_completed' + | 'sign_out'; + +interface AuthEventDetail { + access_token: string; + user_id: string; + app_id: string; +} + +interface UserDataEventDetail { + data: UserData; + meta: RowndUser['meta']; +} + +// Hook Return Type +interface UseRowndReturn { + is_initializing: boolean; + is_authenticated: boolean; + user: RowndUser; + auth: RowndAuth; + requestSignIn: (options?: SignInOptions) => void; + signOut: () => void; + getAccessToken: (options?: TokenOptions) => Promise; + setUser: (data: Partial) => Promise; + setUserValue: (field: string, value: T) => Promise; + manageAccount: () => void; + events: RowndEvents; + passkeys: { + register: () => Promise; + authenticate: () => Promise; + }; +} +``` + +### TypeScript Examples + +#### Type-Safe Authentication Component + +```tsx +import React from 'react'; +import { useRownd } from '@rownd/react'; +import type { SignInOptions, UseRowndReturn } from '@rownd/react'; + +interface AuthButtonProps { + onSuccess?: () => void; + signInMethod?: SignInOptions['method']; +} + +const AuthButton: React.FC = ({ + onSuccess, + signInMethod = 'email' +}) => { + const { + is_initializing, + is_authenticated, + requestSignIn, + signOut + }: UseRowndReturn = useRownd(); + + const handleSignIn = () => { + requestSignIn({ + method: signInMethod, + auto_sign_in: true, + user_data: { + source: 'auth_button' + } + }); + }; + + return ( +
+ {is_initializing && is_authenticated && ( +
Verifying authentication...
+ )} + + {is_initializing && !is_authenticated && ( +
Loading...
+ )} + + {!is_initializing && is_authenticated && ( + + )} + + {!is_initializing && !is_authenticated && ( + + )} +
+ ); +}; + +export default AuthButton; +``` + +#### Type-Safe User Profile Component + +```tsx +import React, { useEffect, useState } from 'react'; +import { useRownd } from '@rownd/react'; +import type { UserData, RowndUser } from '@rownd/react'; + +interface ProfileFormData extends UserData { + marketing_consent?: boolean; + preferences?: { + theme: 'light' | 'dark'; + notifications: boolean; + }; +} + +const UserProfile: React.FC = () => { + const { + user, + setUser, + setUserValue, + is_initializing, + is_authenticated + } = useRownd(); + + const [formData, setFormData] = useState({}); + + useEffect(() => { + if (user.data) { + setFormData(user.data as ProfileFormData); + } + }, [user.data]); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + try { + await setUser(formData); + } catch (error) { + console.error('Failed to update profile:', error); + } + }; + + const handleInputChange = ( + field: keyof ProfileFormData, + value: string | boolean + ) => { + setFormData(prev => ({ ...prev, [field]: value })); + }; + + if (is_initializing) { + return
Loading profile...
; + } + + if (!is_authenticated) { + return
Please sign in to view your profile
; + } + + return ( +
+
+ + handleInputChange('first_name', e.target.value)} + /> +
+ +
+ + handleInputChange('email', e.target.value)} + /> + {user.verified_data.email === formData.email && ( + ✓ Verified + )} +
+ +
+ +
+ + +
+ ); +}; + +export default UserProfile; +``` + +#### Type-Safe API Integration + +```tsx +import React, { useEffect, useState } from 'react'; +import { useRownd } from '@rownd/react'; +import type { TokenOptions } from '@rownd/react'; + +interface ApiResponse { + data: T; + status: number; + message: string; +} + +interface UserPreferences { + theme: 'light' | 'dark'; + notifications: boolean; + timezone: string; +} + +const ApiExample: React.FC = () => { + const { + is_initializing, + is_authenticated, + getAccessToken + } = useRownd(); + + const [preferences, setPreferences] = useState(null); + const [error, setError] = useState(null); + + const fetchPreferences = async () => { + try { + const tokenOptions: TokenOptions = { + waitForToken: true, + timeoutMs: 5000 + }; + + const token = await getAccessToken(tokenOptions); + + const response = await fetch('/api/preferences', { + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json' + } + }); + + const result: ApiResponse = await response.json(); + + if (response.ok) { + setPreferences(result.data); + } else { + throw new Error(result.message); + } + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to fetch preferences'); + } + }; + + useEffect(() => { + if (!is_initializing && is_authenticated) { + fetchPreferences(); + } + }, [is_initializing, is_authenticated]); + + return ( +
+ {is_initializing && is_authenticated && ( +
Loading preferences...
+ )} + + {is_initializing && !is_authenticated && ( +
Checking authentication...
+ )} + + {!is_initializing && is_authenticated && preferences && ( +
+

Your Preferences

+
{JSON.stringify(preferences, null, 2)}
+
+ )} + + {!is_initializing && !is_authenticated && ( +
Please sign in to view your preferences
+ )} + + {error && ( +
Error: {error}
+ )} +
+ ); +}; + +export default ApiExample; +``` + +### Examples + +#### Authentication States + +The Rownd SDK has four possible states based on `is_initializing` and `is_authenticated`: + +```jsx +function AuthStateExample() { + const { + is_initializing, + is_authenticated, + user, + requestSignIn, + signOut + } = useRownd(); + + return ( +
+ {/* State 1: Loading, Authenticated */} + {is_initializing && is_authenticated && ( +
+

Loading authenticated user...

+ +
+ )} + + {/* State 2: Loading, Not Authenticated */} + {is_initializing && !is_authenticated && ( +
+

Loading authentication state...

+ +
+ )} + + {/* State 3: Loaded, Authenticated */} + {!is_initializing && is_authenticated && ( +
+

Welcome {user.data.first_name}!

+ + +
+ )} + + {/* State 4: Loaded, Not Authenticated */} + {!is_initializing && !is_authenticated && ( +
+

Please sign in to continue

+ + +
+ )} +
+ ); +} +``` + +This pattern can be applied to any component that needs to handle authentication states. Here's a more specific example: + +```jsx +function UserProfileManager() { + const { + is_initializing, + is_authenticated, + user + } = useRownd(); + + return ( +
+ {/* Loading States */} + {is_initializing && is_authenticated && ( +
Loading your profile...
+ )} + + {is_initializing && !is_authenticated && ( +
Checking authentication...
+ )} + + {/* Loaded States */} + {!is_initializing && is_authenticated && ( +
+

Your Profile

+
Name: {user.data.first_name} {user.data.last_name}
+
Email: {user.data.email}
+
+ )} + + {!is_initializing && !is_authenticated && ( +
+

Profile Not Available

+

Please sign in to view your profile

+
+ )} +
+ ); +} +``` + +You can also create reusable components for each state: + +```jsx +function LoadingAuthenticatedState({ children }) { + const { is_initializing, is_authenticated } = useRownd(); + return is_initializing && is_authenticated && children; +} + +function LoadingUnauthenticatedState({ children }) { + const { is_initializing, is_authenticated } = useRownd(); + return is_initializing && !is_authenticated && children; +} + +function LoadedAuthenticatedState({ children }) { + const { is_initializing, is_authenticated } = useRownd(); + return !is_initializing && is_authenticated && children; +} + +function LoadedUnauthenticatedState({ children }) { + const { is_initializing, is_authenticated } = useRownd(); + return !is_initializing && !is_authenticated && children; +} + +// Usage Example +function App() { + return ( +
+ + + + + + + + + + + + + + + +
+ ); +} +``` + +This approach can also be used with API calls: + +```jsx +function ProtectedDataComponent() { + const { + is_initializing, + is_authenticated, + getAccessToken + } = useRownd(); + const [data, setData] = useState(null); + + useEffect(() => { + async function fetchData() { + if (!is_initializing && is_authenticated) { + const token = await getAccessToken({ waitForToken: true }); + const response = await fetch('/api/protected', { + headers: { Authorization: `Bearer ${token}` } + }); + setData(await response.json()); + } + } + fetchData(); + }, [is_initializing, is_authenticated, getAccessToken]); + + return ( +
+ {is_initializing && is_authenticated && ( +
Loading protected data...
+ )} + + {is_initializing && !is_authenticated && ( +
Checking access...
+ )} + + {!is_initializing && is_authenticated && ( +
+

Protected Data

+
{JSON.stringify(data, null, 2)}
+
+ )} + + {!is_initializing && !is_authenticated && ( +
Please sign in to view this data
+ )} +
+ ); +} + +### Integration with State Management + +#### Redux Integration + +```jsx +function RowndReduxSync() { + const { is_authenticated, user } = useRownd(); + const dispatch = useDispatch(); + + useEffect(() => { + dispatch({ + type: 'AUTH_STATE_CHANGED', + payload: { + isAuthenticated: is_authenticated, + userData: user.data + } + }); + }, [is_authenticated, user.data, dispatch]); + + return null; +} +``` + +### Best Practices + +1. **Always Check Initialization** + ```jsx + if (is_initializing) { + return ; + } + ``` + +2. **Handle Loading States** +```jsx + if (user.is_loading) { + return
Updating profile...
; + } + ``` + +3. **Use Proper Token Handling** + ```jsx + const token = await getAccessToken({ waitForToken: true }); + ``` + +4. **Implement Error Boundaries** + ```jsx + class RowndErrorBoundary extends React.Component { + // Implementation + } + ``` + +5. **Efficient Token Handling** + ```tsx + // Backend (Node.js/Express example) + import jwt from 'jsonwebtoken'; + + app.get('/api/user-data', (req, res) => { + const token = req.headers.authorization?.split(' ')[1]; + if (!token) return res.status(401).json({ error: 'No token provided' }); + + try { + // The Rownd token already contains app_id and user_id + const decoded = jwt.decode(token); + const { app_id, user_id } = decoded; + + // No need to send these in request body/params + // Just use the data from the token + return res.json({ + message: 'Token already contains necessary identifiers', + app_id, + user_id + }); + } catch (error) { + return res.status(401).json({ error: 'Invalid token' }); + } + }); + ``` + + ```tsx + // Frontend - Efficient API calls + function UserDataComponent() { + const { getAccessToken } = useRownd(); + + const fetchUserData = async () => { + const token = await getAccessToken(); + + // No need to send app_id or user_id in body/params + // They're already in the token + const response = await fetch('/api/user-data', { + headers: { + Authorization: `Bearer ${token}` + } + }); + + const data = await response.json(); + }; + + return
User Data Component
; + } + ``` + +6. **Token Decoding Example** + ```tsx + // Backend utility function + function getTokenData(token: string) { + const decoded = jwt.decode(token); + return { + app_id: decoded.app_id, + user_id: decoded.user_id, + // Other claims available in token + auth_time: decoded.auth_time, + exp: decoded.exp, + iat: decoded.iat + }; + } + ``` + +7. **API Route Best Practices** + ```tsx + // ❌ Don't do this + app.post('/api/update-user', (req, res) => { + const { app_id, user_id, data } = req.body; // Redundant! + // ... handle update + }); + + // ✅ Do this instead + app.post('/api/update-user', (req, res) => { + const token = req.headers.authorization?.split(' ')[1]; + const { app_id, user_id } = jwt.decode(token); + const { data } = req.body; // Only send what's needed + // ... handle update + }); + ``` + +This approach: +- Reduces payload size +- Prevents token/ID mismatch +- Improves security by relying on verified token data +- Simplifies API implementations +- Reduces potential for user spoofing + +### Advanced Features + +#### 1. Custom Sign-in Flows + +```jsx +const { requestSignIn } = useRownd(); + +// Email sign-in +const handleEmailSignIn = (email) => { + requestSignIn({ + identifier: email, + auto_sign_in: true, + post_login_redirect: '/dashboard' + }); +}; + +// Google sign-in +const handleGoogleSignIn = () => { + requestSignIn({ + method: 'google', + post_login_redirect: '/dashboard' + }); +}; +``` + +#### 2. File Uploads + +```jsx +function ProfilePictureUpload() { + const { user } = useRownd(); + + const handleFileUpload = async (file) => { + try { + await user.uploadFile('profile_picture', file); + console.log('Profile picture updated'); + } catch (error) { + console.error('Upload failed:', error); + } + }; + +return ( + handleFileUpload(e.target.files[0])} + /> + ); +} +``` + +For more details on specific APIs and features, refer to the [JavaScript API Reference](/sdk-reference/web/javascript--api-reference). + +### Sign In Request Options + +The `requestSignIn` method accepts several configuration options to customize the sign-in experience: + +```typescript +interface SignInOptions { + // Whether to automatically sign in the user if possible + auto_sign_in?: boolean; + + // Pre-fill the email/phone field + identifier?: string; + + // Authentication method to use + method?: 'email' | 'phone' | 'google' | 'apple' | 'passkey' | 'anonymous'; + + // Override the global post-login redirect + post_login_redirect?: string; + + // Additional user data to store upon sign-in + user_data?: Record; + + // Whether to auto-submit the form (requires identifier) + auto_submit?: boolean; +} +``` + +#### Examples + +```tsx +// Basic sign-in +const handleBasicSignIn = () => { + requestSignIn(); +}; + +// Pre-filled email with auto-submit +const handleAutoSignIn = () => { + requestSignIn({ + identifier: 'user@example.com', + auto_submit: true + }); +}; + +// Google sign-in with custom redirect +const handleGoogleSignIn = () => { + requestSignIn({ + method: 'google', + post_login_redirect: '/dashboard' // Overrides global setting + }); +}; + +// Sign in with additional user data +const handleSignInWithData = () => { + requestSignIn({ + user_data: { + source: 'marketing_campaign', + referral_code: 'REF123' + } + }); +}; +``` + +### HTML Hooks Integration + +While the React SDK provides programmatic control, you can also use HTML data attributes for declarative authentication controls. These work alongside React components: + +```tsx +// Example combining React and HTML hooks +function AuthenticationExample() { +return ( +
+ {/* Trigger sign-in modal */} + + + {/* Auto-display sign-in with pre-filled email */} +
+ + {/* Sign in with custom authenticated text */} + + + {/* Display user data */} +
+ Welcome, {{ first_name }} {{ last_name }}! +
+ + {/* Individual field mapping */} +
+ Email: + {/* Will show verification status automatically */} +
+
+ ); +} +``` + +#### Available HTML Hooks + +| Attribute | Description | Example | +|-----------|-------------|---------| +| `data-rownd-sign-in-trigger` | Creates a clickable sign-in trigger | `` | +| `data-rownd-authenticated-text` | Text to show when authenticated | `data-rownd-authenticated-text="Sign Out"` | +| `data-rownd-authenticated-redirect-url` | URL to redirect to after auth | `data-rownd-authenticated-redirect-url="/dashboard"` | +| `data-rownd-request-sign-in` | Auto-display sign-in modal (closable) | `
` | +| `data-rownd-require-sign-in` | Force sign-in modal (non-closable) | `
` | +| `data-rownd-default-user-identifier` | Pre-fill email/phone | `data-rownd-default-user-identifier="user@example.com"` | +| `data-rownd-field-interpolate` | Template user data | `
Hello {{first_name}}!
` | +| `data-rownd-field-mapping` | Display specific user field | `` | + +#### Combining React and HTML Approaches + +You can mix programmatic and declarative approaches: + +```tsx +function HybridAuthExample() { + const { is_authenticated, user } = useRownd(); + + const handleCustomSignIn = () => { + requestSignIn({ + method: 'email', + identifier: user.data.email, + post_login_redirect: '/welcome' + }); + }; + + return ( +
+ {/* Programmatic control */} + + + {/* HTML hook with dynamic content */} +
+ Get Started +
+ + {/* Automatic sign-in prompt */} + {!is_authenticated && ( +
+ )} + + {/* User data display */} +
+ Account: {{ email }} + Status: {{ subscription_status }} +
+
+ ); +} +``` + +### Best Practices for Authentication Flow + +1. **Global vs. Local Redirects** + ```tsx + // Global redirect in provider + + + + + // Local override in component + const handleSignIn = () => { + requestSignIn({ + post_login_redirect: '/special-landing' // Takes precedence + }); + }; + ``` + +2. **Progressive Enhancement** + ```tsx + function AuthenticationFlow() { + const { is_initializing, is_authenticated, user } = useRownd(); + + // First, try HTML hooks + if (!is_authenticated) { + return ( +
+ ); + } + + // Then, enhance with React + return ( +
+

Welcome {user.data.first_name}!

+ +
+ ); + } + ``` + +3. **Handling Different Auth States** + ```tsx + function AuthStateManager() { + return ( +
+ {/* Request sign-in for new users */} +
+ + {/* Force sign-in for protected content */} + +
+ + + {/* Custom experience for returning users */} +
+ Sign In +
+
+ ); + } + ``` + +### Account Management + +#### Using manageAccount() + +The `manageAccount()` function provides a pre-built, customizable account management interface that saves significant development time. This Rownd-generated system handles common user management tasks out of the box. + +```tsx +function ProfileManager() { + const { manageAccount, is_authenticated } = useRownd(); + + return ( +
+

Account Settings

+ +
+ ); +} +``` + +#### Features Included + +The account management interface provides: + +| Feature | Description | +|---------|-------------| +| Profile Editing | Users can update their basic information (name, email, etc.) | +| Email Verification | Handles email verification status and re-verification | +| Password Management | Change password and set up passwordless options | +| Connected Accounts | Manage social logins and connected services | +| Security Settings | 2FA setup, passkey management, session control | +| Data Access | View and download personal data | +| Account Deletion | Self-service account removal option | + +#### Customization Options + +You can customize the account management interface through the Rownd Dashboard: + +1. **Branding** + - Custom colors and themes + - Logo placement + - Typography settings + +2. **Field Configuration** + - Show/hide specific fields + - Mark fields as required + - Add custom fields + - Set field validation rules + +3. **Feature Toggles** + - Enable/disable specific features + - Configure verification requirements + - Set up data retention policies + +#### Integration Example + +```tsx +function AccountSection() { + const { + manageAccount, + is_authenticated, + user, + is_initializing + } = useRownd(); + + if (is_initializing) { + return
Loading account settings...
; + } + + return ( +
+ {!is_authenticated && ( +
+

Please sign in to manage your account

+ +
+ )} + + {is_authenticated && ( + <> +
+

Account Overview

+

Welcome, {user.data.first_name}!

+ {user.verified_data.email && ( + ✓ Verified Email + )} +
+ +
+ +

+ Update your profile, security settings, and connected accounts +

+
+ + )} +
+ ); +} +``` + +#### Best Practices + +1. **Accessibility** + ```tsx + + ``` + +2. **Context-Aware Placement** + ```tsx + function UserMenu() { + const { manageAccount } = useRownd(); + + return ( + +
  • Dashboard
  • +
  • + +
  • +
  • Help
  • +
    + ); + } + ``` + +3. **Error Handling** + ```tsx + function SafeAccountManager() { + const { manageAccount } = useRownd(); + + const handleAccountClick = () => { + try { + manageAccount(); + } catch (error) { + console.error('Failed to open account manager:', error); + // Show fallback UI or error message + } + }; + + return ( + + ); + } + ``` + +By using `manageAccount()`, you get a complete user account management system without building and maintaining custom interfaces. This significantly reduces development time while providing a consistent, secure, and feature-rich experience for your users. + +### Accessing User Data + +There are two ways to access user data in your application: + +1. **Using the useRownd Hook (Recommended)** +```tsx +function UserProfile() { + const { user } = useRownd(); + + // Access user data directly + return ( +
    +
    {user.data.first_name}
    +
    {user.data.email}
    +
    {user.data.custom_field}
    +
    + ); +} +``` + +2. **Using HTML Data Attributes** +```html + +
    + Hello, {{ first_name }} {{ last_name }}! + Your email is: {{ email }} +
    + + +
    + First Name: + Email: +
    +``` + +#### Important Notes: +- Always access user data through `user.data` when using the hook +- Fields are accessed directly in HTML templates (e.g., `{{ first_name }}` not `{{ user.data.first_name }}`) +- Both methods require being within a `` context +- Both methods automatically update when user data changes + +#### Combined Example: +```tsx +function UserDashboard() { + const { user, is_authenticated } = useRownd(); + + if (!is_authenticated) { + return
    Please sign in
    ; + } + + return ( +
    + {/* Programmatic access with useRownd */} +

    Welcome, {user.data.first_name}!

    + + {/* HTML hook for complex templates */} +
    + Account Details: + Email: {{ email }} + Subscription: {{ subscription_type }} + Member since: {{ join_date }} +
    + + {/* Mix both approaches */} +
    +

    Profile

    + {user.data.profile_picture && ( + + )} +
    +
    +
    + ); +} +``` diff --git a/rownd-docusaurus/sdk-reference/web/remix.mdx b/rownd-docusaurus/sdk-reference/web/remix.mdx new file mode 100644 index 0000000..fe9c679 --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/remix.mdx @@ -0,0 +1,338 @@ +--- +title: "Remix" +description: Remix SDK reference +icon: r +--- + +### Installation + +Simply run `npm install @rownd/remix` or `yarn add @rownd/remix`. + +### Setup + +The library provides a React provider for the client and a higher-order +function for the server. + +In your app's `root.tsx` file, use the Remix Rownd provider to wrap children, +likely before other providers: + +root.tsx +```jsx +... +import { RemixRowndProvider } from '@rownd/remix'; +... + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + + {children} + + + + + + ); +} +``` + +In your app's `entry.server.ts` file, add the Rownd handle request higher-order +function with your server's request handler `handleRequest`: + +entry.server.ts +```jsx +... +import { withRowndHandleRequest } from '@rownd/remix/server'; +... + +export default withRowndHandleRequest(function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + loadContext: AppLoadContext +) { + return ... +}); +``` + +### Protected component +To protect a component from being accessed by unauthenticated users, you can use +the `withRowndRequireSignIn` higher-order component and the `withRowndLoader` +higher-order function. + +```jsx +import type { LoaderFunctionArgs } from '@remix-run/node'; +import { useLoaderData } from '@remix-run/react'; + +import { + withRowndRequireSignIn, + useRownd, +} from '@rownd/remix'; + +import { + withRowndLoader, +} from '@rownd/remix/server'; + +export const loader = withRowndLoader(async function ( + { context, request }: LoaderFunctionArgs, + { user_id, access_token } +) { + + const authenticatedFetch = await fetch('https:random.com/posts',{ + headers: { + Authorization: `Bearer ${access_token}`, + }, + }) + + const posts = await authenticatedFetch.json(); + + return { posts, user_id }; +}); + +function Index() { + const { signOut } = useRownd(); + const { posts, user_id } = useLoaderData(); + + return ( +
    + ... +

    User ID: {user_id}

    + +
    + ); +} + +function Fallback() { + return
    Loading...
    ; +} + +export default withRowndRequireSignIn(Index, useLoaderData, Fallback); +``` + +### Client-side API reference + +Please see the [React SDK](sdk-reference/web/react) for details on Rownd Client React API's. + + +Most API methods are made available via the Rownd Provider and its associated +`useRownd` React hook. Unless otherwise noted, we're assuming that you're using +hooks. + +#### requestSignIn() + +Trigger the Rownd sign in dialog + +```jsx +const { requestSignIn } = useRownd(); + +requestSignIn({ + auto_sign_in: false, // optional + identifier: "me@company.com" || "+19105551212", // optional +}); +``` + +- `auto_sign_in: boolean` \- when `true`, automatically trigger a sign-in + attempt _if_ `identifier` is included or an email address or phone number has + already been set in the user data. + +- `identifier: string` \- an email address or phone number (in E164 format) to + which a verification message may be sent. If the Rownd app is configured to + allow unverified users, then sign-in will complete without verification if the + user has not signed in previously. + +#### signOut() + +Sign out the user and clear their profile, returning them to a completely +unauthenticated state. + +```jsx +const { signOut } = useRownd(); +signOut(); +``` + +#### getAccessToken() + +Retrieves the active, valid access token for the current user. + +```jsx +const { getAccessToken } = useRownd(); + +let accessToken = await getAccessToken({ + waitForToken: false, +}); +``` + +- `waitForToken: boolean` \- when `true`, if no access token is present or if + it's expired, the promise will not resolve until a valid token is available. + While unlikely, this could result in waiting forever. + +**is_initializing** + +`is_initializing` will be `true` until the Hub has fully loaded, recalled its +state, and resolved the current user's authentication status. This usually takes +only a few milliseconds, but if you make decisions that depend on the +`is_authenticated` flag while `is_initializing` is still `true`, your code/logic +may not work as you expect. + +```jsx +const { is_initializing } = useRownd(); + +if (is_initializing) { + // return loading state or null +} +``` + +#### is_authenticated + +```jsx +const { is_authenticated } = useRownd(); + +return ( + <> + {is_authenticated && } + {!is_authenticated && } + +); +``` + +#### access_token + +Represents the current access token for the user. + +```jsx +const { access_token } = useRownd(); + +useEffect(() => { + axios({ + method: 'post', + url: '/api/sessions' + headers: { + authorization: `Bearer ${access_token}` + } + }).then(console.log); +}, [access_token]); +``` + +#### user + +Represents information about the current user, specifically their profile +information. In the example below, we use the existing data to display the +current value of `first_name` in a form field, update a local copy of that data +as the user changes it, and then save the changes to Rownd once the user submits +the form. + +```jsx +const { user, setUser } = useRownd(); + +const [profile, setProfile] = useState(user.data); + +return ( +
    setUser(profile)}> + + +
    +); +``` + +#### setUser + +The `setUser` function allows you to update a user's profile information within the Rownd platform. You can modify user attributes such as `first_name`, `last_name`, and other properties by passing an object with the relevant fields. + +```jsx +const { setUser } = useRownd(); + +setUser({ + first_name: "Alice", + last_name: "Ranier", +}); +``` + +#### setUserValue + +The `setUserValue` function allows you to update a specific attribute of the user's profile within the Rownd platform. Instead of passing an entire user object, you can update individual fields by specifying the key (attribute name) and value. + +```jsx +const { setUserValue } = useRownd(); + +setUserValue("first_name", "Alice"); +``` + +#### manageAccount() + +The `manageAccount()` function allows users to view and update their profile information within the Rownd platform. This function opens the user’s account management interface, where they can review and modify personal details such as their name, email, and other profile attributes. + +```jsx +const { manageAccount } = useRownd(); + +; +``` + +#### passkeys + +Rownd offers passkey-based authentication, allowing users to create and authenticate using a secure passkey. The `register` function starts the process of creating a new passkey for the user, while the `authenticate` function validates an existing passkey to authenticate the user. + +```jsx +const { passkeys } = useRownd(); + +
    + + +
    ; +``` + +#### RequireSignIn + +The `RequireSignIn` component is a wrapper that triggers the sign-in process when the component it wraps is rendered. It ensures that the user is signed in before accessing the content of the wrapped component. If the user is not authenticated, the sign-in process will automatically begin when the component mounts. + +```jsx +const App = () => { + return ( + +

    Home page

    + + ); +}; +``` + +#### SignedIn + +The `SignedIn` component is used to conditionally render its children only when the user is authenticated. If the user is not signed in, the wrapped content will not be displayed. + +```jsx +const App = () => { + return ( + + + + ); +}; +``` + +#### SignedOut + +The `SignedOut` component is the counterpart to `SignedIn`. It renders its children only when the user is not authenticated. If the user is signed in, the wrapped content will not be displayed. + +```jsx +const App = () => { + return ( + + + + ); +}; +``` diff --git a/rownd-docusaurus/sdk-reference/web/ruby-on-rails.mdx b/rownd-docusaurus/sdk-reference/web/ruby-on-rails.mdx new file mode 100644 index 0000000..b9e27ca --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/ruby-on-rails.mdx @@ -0,0 +1,205 @@ +--- +title: "Ruby on Rails" +description: Ruby on Rails SDK reference +icon: gem +--- + +Rownd's support for Ruby on Rails is powered by our Ruby gem named +`devise-rownd`. This gem is an implementation of a custom strategy for the +popular [Devise](https://github.com/heartcombo/devise) framework. It works in +tandem with the Rownd Hub, a javascript snippet embedded in your website. With +this gem installed, Rownd handles all aspects of user authentication and gives +you the tools to customize the user experience on your site. + +## Installation + +Add this line to your application's `Gemfile`: + +```rb +gem 'devise-rownd' +``` + +And then execute: + +``` +$ bundle +``` + +Or install it yourself as: + +```bash +$ gem install devise-rownd +``` + +### Mount the Engine + +Add this to your `config/routes.rb` file + +```rb +mount Devise::Rownd::Engine, at: '/api/auth/rownd' +``` + +### Rownd Hub + +Follow [these instructions](/sdk-reference/web/javascript--browser) +to install the Rownd Hub. You'll want to ensure it runs on every page of your +application, so be sure to add it as a common in your Rails JS packs. Here's the +easiest way to do that: + +1. Create a new file in your JS packs directory called `rownd.js` and paste the + JS snippet that you got from the instructions listed above. + +2. 2. Add the following API callbacks to your Javascript: + +```js +_rphConfig.push([ + "setPostAuthenticationApi", + { + method: "post", + url: "/api/auth/rownd/authenticate", + }, +]); + +_rphConfig.push([ + "setPostSignOutApi", + { + method: "POST", + url: "/api/auth/rownd/sign_out", + }, +]); + +_rphConfig.push([ + "setPostUserDataUpdateApi", + { + method: "POST", + url: "/api/auth/rownd/update_data", + }, +]); +``` + + + The path prefix `/api/auth/rownd` must match the `Devise::Rownd::Engine` mount + path that you specified in your Rails routes + + +1. Finally, include the Javascript pack in your application layout. + +```js + + <%= show_rownd_signin_if_required %> + <%= yield %> + <%= javascript_pack_tag 'rownd', 'data-turbolinks-track': 'reload' %> + +``` + +There are two key pieces that you must include in the layout: + +`<%= show_rownd_signin_if_required %>` This renders the Rownd sign-in modal to +prompt the user for authentication when your app explicitly requires it in a +controller + +`<%= javascript_pack_tag 'rownd', 'data-turbolinks-track': 'reload' %>` Tells +Rails to include the `rownd` Javascript pack. We also tell Turbolinks to include +the script on page reloads + +## Usage + +For this to work, you need to define these key environment variables: + +- `ROWND_APP_KEY` \- Your Rownd application key + +- `ROWND_APP_SECRET` \- Your Rownd application secret + +You can get all of these values from the [Rownd Platform](https://app.rownd.io) + +### Users + +This gem provides a new Devise module named `:rownd_authenticatable`. In your +`user` model, you can tell Devise to use it like this: + +```rb +class User < ApplicationRecord + devise :rownd_authenticatable + + ... +end +``` + +Now, in your `config/routes.rb` file, add the following: + +```rb +Rails.application.routes.draw do + devise_for :users + ... + + mount Devise::Rownd::Engine, at: '/api/auth/rownd' +end +... +``` + +### Require Authentication + +You can require authentication on a controller's actions the same way you would +for any Devise strategies. + +```rb +class MyController < ApplicationController + before_action :authenticate_user! + + ... +end +``` + +Now, when a user navigates to a route that requires authentication, Devise will +prompt the user to sign into Rownd if a user is not already signed in. + +### Customizing the page using the `current_user` + +In any of your controllers, views, or helpers, you have access to the currently +authenticated user via the `current_user` variable. You can use it to customize +your page content like this: + +```rb +Hello, <%= current_user.first_name %>! +``` + +The `current_user` object has all of the fields specified in your Rownd +application's schema. If the user doesn't have a value for a particular field, +it will be `nil` + +### Extending the `current_user` model + +You can extend the `current_user` object by modifying the `Devise::Rownd::User` +class. This can be very helpful if you want to have additional functions that +aggregate data across multiple fields, or perform some logic and return the +result. + +For instance, you might want a function called `admin?` that will return if the +current user has an `'admin'` role. To extend the `current_user` object, add a +new initializer in `config/initializers` called `devise_rownd.rb`. In there you +can modify the `Devise::Rownd::User` like this: + +```rb +Devise::Rownd::User.class_eval do + def admin? + roles&.include?('admin') + end + + def display_name + fullname = "#{first_name} #{last_name}" + fullname.present? ? fullname.strip.upcase : email&.upcase + end + + ... +end +``` + +Now, you can call things like `current_user.admin?` and +`current_user.display_name` + +### Further customization + +All of the other Rownd HTML attributes work as well. You can see a full list of +them [here](/rownd/sdk-reference/web/javascript-browser#hooks). This means you +have the ability to customize the page with pure HTML, rather than Ruby code if +you prefer. diff --git a/rownd-docusaurus/sdk-reference/web/vue.mdx b/rownd-docusaurus/sdk-reference/web/vue.mdx new file mode 100644 index 0000000..4c3e48a --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/vue.mdx @@ -0,0 +1,262 @@ +--- +title: "Vue" +description: + "Easily add Rownd instant accounts and authentication to your Vue-based + project." +icon: vuejs +--- + +## Installation + +Simply run `npm install @rownd/vue` or `yarn add @rownd/vue`. + + + This plugin only works with Vue 3 and above! If you need support for Vue 2, + please [get in + touch](mailto:support@rownd.io?subject=Support%20for%20Vue%20v2). + + +## Usage + +The library provides a Vue plugin and injector hook for Vue-based apps. + +In your app's main entrypoint, install the Rownd plugin like in the following +example: + +```jsx +import { createApp } from "vue"; +import { RowndPlugin } from "@rownd/vue"; // Import the plugin + +import App from "./App.vue"; +import router from "./router"; + +const app = createApp(App); + +// Initialize the plugin. Be sure to include your app key! +app.use(RowndPlugin, { + appKey: "", +}); + +app.use(router); + +app.mount("#app"); +``` + +### Plugin options + +- `appKey` (required): This is the key generated by the + [Rownd dashboard](https://app.rownd.io/). + +- `rootOrigin` (optional): If you're using Rownd across multiple domains (e.g., + `rownd.io` and `app.rownd.io`), set this to the "root" _origin_ (e.g., + https://rownd.io). + +Later on within your app's components, you can use the Rownd injector/hook to +access the Rownd browser API: + +```jsx + + + +``` + +### API reference + +Most API methods are made available via the Rownd plugin and its associated +`useRownd` injector. Javascript will be used for most examples, but these should +work with Vue directives as well. + +#### `requestSignIn()` + +Trigger the Rownd sign in dialog. This can be used from a link/button or +programmatically, if you wanted to allow a user to use parts of your app without +signing in, but then trigger the sign-in prior to them doing something +important. + +```jsx +const rownd = useRownd(); + +rownd.requestSignIn({ + auto_sign_in: false, // optional + identifier: "me@company.com" || "+19105551212", // optional +}); +``` + +- `auto_sign_in: boolean` \- when `true`, automatically trigger a sign-in + attempt _if_ `identifier` is included or an email address or phone number has + already been set in the user data. + +- `identifier: string` \- an email address or phone number (in E164 format) to + which a verification message may be sent. If the Rownd app is configured to + allow unverified users, then sign-in will complete without verification if the + user has not signed in previously. + +**signOut()** + +Sign out the user and clear their profile, returning them to a completely +unauthenticated state. + +```jsx + + + +``` + +**getAccessToken()** + +Retrieves the active, valid access token for the current user. + +```jsx +const rownd = useRownd(); +let accessToken = await rownd.getAccessToken({ + waitForToken: false, +}); +``` + +- `waitForToken: boolean` \- when `true`, if no access token is present or if + it's expired, the promise will not resolve until a valid token is available. + While unlikely, this could result in waiting forever. + +**is_initializing** + +`is_initializing` will be `true` until the Hub has fully loaded, recalled its +state, and resolved the current user's authentication status. This usually takes +only a few milliseconds, but if you make decisions that depend on the +`is_authenticated` flag while `is_initializing` is still `true`, your code/logic +may not work as you expect. + +```jsx + + + +``` + +**is_authenticated** + +Indicates whether the current user is signed in or not. + +```jsx + + + +``` + +**access_token** + +Represents the current access token for the user. + +```jsx + +``` + +**user** + +Represents information about the current user, specifically their profile +information. In the example below, we use the existing data to display the +current value of `first_name` in a form field, and then immediately sync changes +to Rownd as the user updates the form field. + +```jsx + + + +``` + +You might not want to sync changes to Rownd immediately, but rather wait for the +user to click a button, as in the following example: + +```jsx + + + + +``` + +**Merge data into the user profile programmatically** + +```jsx +const rownd = useRownd(); +rownd.user.set({ + first_name: "Juliet", + last_name: "Rose", +}); +``` + +Set a specific field in the user profile programmatically + +```jsx +const rownd = useRownd(); +user.setValue('first_name', 'Alice'); +``` diff --git a/rownd-docusaurus/sdk-reference/web/wordpress---woocommerce.mdx b/rownd-docusaurus/sdk-reference/web/wordpress---woocommerce.mdx new file mode 100644 index 0000000..036b18b --- /dev/null +++ b/rownd-docusaurus/sdk-reference/web/wordpress---woocommerce.mdx @@ -0,0 +1,79 @@ +--- +title: "WordPress / WooCommerce" +description: "Add Rownd to your WordPress site with a simple plugin" +icon: wordpress +--- + +When you install the Rownd plugin for WordPress, you'll bring our powerfully +simple authentication and user account capabilities into your website, blog, or +e-commerce site. + +Rownd integrates with the existing WordPress user management system, which means +we're compatible with WooCommerce and many other WordPress addons! + +Whether you're accepting user signups already or want to start, Rownd makes it +ultra-simple to get visitors and customers up and running quickly. Easily +trigger our sign-in dialog by setting some HTML data attributes in your code or +writing some simple Javascript and we'll handle getting your users verified and +signed in using our unique, passwordless approach. + +## To get started, you'll need: + +1. A free [Rownd account](https://app.rownd.io) + +2. A Rownd [app key](https://docs.rownd.io/configuration/app-credentials) + +3. Add [allowed web origins](https://docs.rownd.io/security/attack-mitigation/domain-allow-list#configuring-the-domain-allow-list) + +Once you install this plugin, drop your app key and secret into our settings and +you'll be good to go! + +## Installation + +### Automated installation + +1. Open your WordPress site's admin dashboard. This is usually something like + `https://mycompany.com/wp-admin`. + +2. Navigate to **Plugins > Add new.** + +3. In the text field labeled "Search plugins," type **Rownd** and wait a moment + for the search to load the results. + ![](/sdk-reference/images/wordpress_plugin_search.png) + +4. Click **Install** then click **Activate.** + +5. In the sidebar, click **Rownd** followed by Settings. + +6. Enter your Rownd app keys obtained from the [Rownd platform](https://app.rownd.io) + + ![](/sdk-reference/images/wordpress_plugin_appkey.png) + +7. Click **Save settings** + +### Manual install + +1. Visit the + [Rownd plugin details](https://wordpress.org/plugins/rownd-accounts-and-authentication/) + within the WordPress plugin directory. + +2. Click **Download** to grab the latest plugin `.zip` file. + +3. Extract the contents of the file into a folder called + `rownd-accounts-and-authentication` within your `wp-content/plugins` folder. + The naming here is important! + +4. Open your site's WordPress Admin dashboard, navigate to the plugin list, and + click the **Activate** link in the row entitled "Rownd Accounts and + Authentication." + ![](/sdk-reference/images/image.png) + +### Video guide + +
    \ No newline at end of file diff --git a/rownd-docusaurus/sidebars.api.ts b/rownd-docusaurus/sidebars.api.ts new file mode 100644 index 0000000..0084b65 --- /dev/null +++ b/rownd-docusaurus/sidebars.api.ts @@ -0,0 +1,150 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; + +const sidebars: SidebarsConfig = { + apiSidebar: [ + { + type: 'category', + label: 'Get Started', + items: [ + { + type: 'category', + label: 'Authentication', + items: [ + 'authentication/overview', + 'authentication/retrieve-jwk', + 'authentication/retrieve-oidc', + ], + }, + ], + }, + { + type: 'category', + label: 'App-Scoped Endpoints', + items: [ + { + type: 'category', + label: 'Groups', + items: [ + 'groups/overview', + 'groups/platform/group-create', + 'groups/platform/group-read', + 'groups/platform/group-update', + 'groups/platform/group-delete', + 'groups/platform/group-list', + ], + }, + { + type: 'category', + label: 'Group Invitations', + items: [ + 'groups/platform/invites/invite-create', + 'groups/platform/invites/invite-read', + 'groups/platform/invites/invite-update', + 'groups/platform/invites/invite-delete', + 'groups/platform/invites/invite-list', + ], + }, + { + type: 'category', + label: 'Group Members', + items: [ + 'groups/platform/members/member-create', + 'groups/platform/members/member-read', + 'groups/platform/members/member-update', + 'groups/platform/members/member-delete', + 'groups/platform/members/member-list', + ], + }, + { + type: 'category', + label: 'Magic Links', + items: ['authentication/create-magic-link'], + }, + { + type: 'category', + label: 'OpenID Clients', + items: [ + 'oidc/clients/list', + 'oidc/clients/create', + 'oidc/clients/read', + 'oidc/clients/update', + 'oidc/clients/delete', + ], + }, + { + type: 'category', + label: 'User Profiles', + items: [ + 'user-profiles/app/insert-update', + 'user-profiles/app/get-user-data', + 'user-profiles/app/update-patch', + 'user-profiles/app/delete', + 'user-profiles/app/list-user-profiles', + 'user-profiles/app/retrieve-field', + 'user-profiles/app/update-field', + 'user-profiles/app/get-sample-data', + ], + }, + { + type: 'category', + label: 'User Sessions', + items: ['user-sessions/app/revoke-user-sessions'], + }, + ], + }, + { + type: 'category', + label: 'User-Scoped Endpoints', + items: [ + { + type: 'category', + label: 'Groups', + items: [ + 'groups/overview', + 'groups/user/group-create', + 'groups/user/group-read', + 'groups/user/group-update', + 'groups/user/group-delete', + 'groups/user/group-list', + ], + }, + { + type: 'category', + label: 'Group Invitations', + items: [ + 'groups/user/invites/invite-create', + 'groups/user/invites/invite-read', + 'groups/user/invites/invite-update', + 'groups/user/invites/invite-delete', + 'groups/user/invites/invite-list', + ], + }, + { + type: 'category', + label: 'Group Members', + items: [ + 'groups/user/members/member-create', + 'groups/user/members/member-read', + 'groups/user/members/member-update', + 'groups/user/members/member-delete', + 'groups/user/members/member-list', + ], + }, + { + type: 'category', + label: 'User Profiles', + items: [ + 'user-profiles/user/get-user-data', + 'user-profiles/user/update-put', + 'user-profiles/user/retrieve-field', + 'user-profiles/user/update-field', + ], + }, + ], + }, + ], +}; + +export default sidebars; + + diff --git a/rownd-docusaurus/sidebars.sdk.ts b/rownd-docusaurus/sidebars.sdk.ts new file mode 100644 index 0000000..e644b06 --- /dev/null +++ b/rownd-docusaurus/sidebars.sdk.ts @@ -0,0 +1,68 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; + +const sidebars: SidebarsConfig = { + sdkSidebar: [ + { + type: 'category', + label: 'Get Started', + collapsible: false, + items: ['overview'], + }, + { + type: 'category', + label: 'Mobile', + collapsible: false, + items: [ + 'mobile/overview', + 'mobile/android', + 'mobile/flutter', + 'mobile/ios', + 'mobile/react-native', + 'mobile/expo', + ], + }, + { + type: 'category', + label: 'Web', + collapsible: false, + items: [ + 'web/overview', + { + type: 'category', + label: 'Javascript', + items: [ + 'web/javascript--api-reference', + 'web/javascript--browser', + ], + }, + 'web/angular', + 'web/html', + 'web/nextjs', + 'web/react', + 'web/remix', + 'web/ruby-on-rails', + 'web/vue', + 'web/wordpress---woocommerce', + ], + }, + { + type: 'category', + label: 'Backend / Server', + collapsible: false, + items: [ + 'backend/overview', + 'web/django--python', + 'web/go', + 'web/node-js', + 'web/net-core', + 'web/ruby-on-rails', + 'backend/convex', + 'web/wordpress---woocommerce', + ], + }, + ], +}; + +export default sidebars; + + diff --git a/rownd-docusaurus/sidebars.ts b/rownd-docusaurus/sidebars.ts new file mode 100644 index 0000000..1c1b83c --- /dev/null +++ b/rownd-docusaurus/sidebars.ts @@ -0,0 +1,204 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; + +const sidebars: SidebarsConfig = { + mainSidebar: [ + { + type: 'category', + label: 'Welcome', + collapsible: false, + items: [ + 'welcome/overview', + 'welcome/rownd-features', + 'welcome/getting-started', + { + type: 'category', + label: 'Migrating to Rownd', + items: [ + 'migration/overview', + 'migration/auth0', + 'migration/cognito', + 'migration/firebase', + ], + }, + { + type: 'category', + label: 'Comparing Rownd', + items: [ + 'welcome/comparisons/overview', + 'welcome/comparisons/auth0', + 'welcome/comparisons/clerk', + 'welcome/comparisons/cognito', + 'welcome/comparisons/firebase', + 'welcome/comparisons/supabase', + 'welcome/comparisons/zitadel', + ], + }, + ], + }, + { + type: 'category', + label: 'Configuration', + collapsible: false, + items: [ + 'configuration/overview', + 'configuration/applications', + 'configuration/app-credentials', + { + type: 'category', + label: 'Authentication methods', + items: [ + 'configuration/authentication-methods/overview', + 'configuration/authentication-methods/instant-users', + 'configuration/authentication-methods/email', + 'configuration/authentication-methods/phone-sms', + 'configuration/authentication-methods/apple', + 'configuration/authentication-methods/google', + 'configuration/authentication-methods/passkeys', + 'configuration/authentication-methods/guests', + 'configuration/authentication-methods/oauth', + 'configuration/authentication-methods/unverified', + 'configuration/authentication-methods/existing-authentication', + ], + }, + { + type: 'category', + label: 'Automations', + items: [ + 'configuration/automations/overview', + 'configuration/automations/sign-in-prompt', + ], + }, + { + type: 'category', + label: 'Cross-domain authentication', + items: [ + 'configuration/cross-domain/overview', + 'configuration/cross-domain/implementation', + ], + }, + { + type: 'category', + label: 'Custom domains', + items: [ + 'configuration/custom-domains/overview', + 'configuration/custom-domains/dns-records', + ], + }, + { + type: 'category', + label: 'Customizations', + items: [ + 'configuration/customizations/global-style', + 'configuration/customizations/email-customization', + 'configuration/customizations/sub-brands', + ], + }, + { + type: 'category', + label: 'Integrations', + items: [ + 'configuration/integrations/overview', + 'configuration/integrations/auth0', + 'configuration/integrations/firebase/overview', + 'configuration/integrations/firebase/google-cloud-platform-requirements', + 'configuration/integrations/firebase/realtime-database--defining-user-data-locations', + 'configuration/integrations/firebase/realtime-database', + 'configuration/integrations/airtable', + 'configuration/integrations/hubspot', + 'configuration/integrations/mailerlite', + 'configuration/integrations/token-validator', + 'configuration/integrations/webhooks', + ], + }, + { + type: 'category', + label: 'Magic links', + items: [ + 'magic-links/overview', + 'magic-links/authenticated', + 'magic-links/unauthenticated', + 'magic-links/platform', + 'magic-links/url-parameters', + ], + }, + { + type: 'category', + label: 'Mobile', + items: [ + 'configuration/mobile/overview', + 'configuration/mobile/android', + 'configuration/mobile/android-instant', + 'configuration/mobile/ios', + 'configuration/mobile/ios-app-clip', + 'configuration/mobile/mobile-app-settings', + ], + }, + { + type: 'category', + label: 'OpenID Connect', + items: ['configuration/oidc/overview'], + }, + { + type: 'category', + label: 'User accounts', + items: [ + 'configuration/user-accounts/overview', + 'configuration/user-accounts/user-profiles', + 'configuration/user-accounts/platform-user-table', + 'configuration/user-accounts/progressive-profiles', + 'configuration/user-accounts/groups', + ], + }, + { + type: 'category', + label: 'Payments', + items: [ + 'payments/overview', + 'payments/app-setup', + 'payments/stripe', + ], + }, + { + type: 'category', + label: 'Web3', + items: [ + 'configuration/web3/near-overview', + 'configuration/web3/near-examples', + ], + }, + ], + }, + { + type: 'category', + label: 'Administration', + collapsible: false, + items: [ + 'administration/account', + 'administration/teams', + ], + }, + { + type: 'category', + label: 'Security', + collapsible: false, + items: [ + 'security/overview', + { + type: 'category', + label: 'Attack mitigation', + items: [ + 'security/attack-mitigation/overview', + 'security/attack-mitigation/domain-allow-list', + 'security/attack-mitigation/suspicious-ip-throttling', + 'security/attack-mitigation/bot-detection', + ], + }, + 'security/SOC2-type2', + 'security/hipaa-ready', + 'security/responsible-disclosure', + ], + }, + ], +}; + +export default sidebars; diff --git a/rownd-docusaurus/src/components/RowndMDX/Accordion.tsx b/rownd-docusaurus/src/components/RowndMDX/Accordion.tsx new file mode 100644 index 0000000..4138706 --- /dev/null +++ b/rownd-docusaurus/src/components/RowndMDX/Accordion.tsx @@ -0,0 +1,17 @@ +import React, {PropsWithChildren, useState} from 'react'; + +type Props = PropsWithChildren<{title: string}>; + +export default function Accordion({title, children}: Props) { + const [open, setOpen] = useState(false); + return ( +
    + + {open &&
    {children}
    } +
    + ); +} + + diff --git a/rownd-docusaurus/src/components/RowndMDX/Card.tsx b/rownd-docusaurus/src/components/RowndMDX/Card.tsx new file mode 100644 index 0000000..0c5d78a --- /dev/null +++ b/rownd-docusaurus/src/components/RowndMDX/Card.tsx @@ -0,0 +1,44 @@ +import React, {PropsWithChildren} from 'react'; +import Link from '@docusaurus/Link'; +import Icon from './Icon'; + +type Props = PropsWithChildren<{ + title: string; + icon?: React.ReactNode | string; + href?: string; + ['icon-type']?: string; +}>; + +export default function Card({title, icon, href, children}: Props) { + const content = ( +
    +
    +
    + {typeof icon === 'string' ? : icon} +
    +

    {title}

    +
    + {children &&
    {children}
    } +
    + ); + return href ? ( + + {content} + + ) : ( + content + ); +} + + diff --git a/rownd-docusaurus/src/components/RowndMDX/CardGroup.tsx b/rownd-docusaurus/src/components/RowndMDX/CardGroup.tsx new file mode 100644 index 0000000..5dc55ea --- /dev/null +++ b/rownd-docusaurus/src/components/RowndMDX/CardGroup.tsx @@ -0,0 +1,18 @@ +import React, {PropsWithChildren} from 'react'; + +export default function CardGroup({children}: PropsWithChildren) { + return ( +
    + {children} +
    + ); +} + + diff --git a/rownd-docusaurus/src/components/RowndMDX/CodeGroup.tsx b/rownd-docusaurus/src/components/RowndMDX/CodeGroup.tsx new file mode 100644 index 0000000..9e9e800 --- /dev/null +++ b/rownd-docusaurus/src/components/RowndMDX/CodeGroup.tsx @@ -0,0 +1,7 @@ +import React, {PropsWithChildren} from 'react'; + +export default function CodeGroup({children}: PropsWithChildren) { + return
    {children}
    ; +} + + diff --git a/rownd-docusaurus/src/components/RowndMDX/Endpoint.tsx b/rownd-docusaurus/src/components/RowndMDX/Endpoint.tsx new file mode 100644 index 0000000..31f87a8 --- /dev/null +++ b/rownd-docusaurus/src/components/RowndMDX/Endpoint.tsx @@ -0,0 +1,41 @@ +import React from 'react'; + +type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + +type Props = { + method: HttpMethod; + path: string; + baseUrls?: string[]; +}; + +const methodToClass: Record = { + GET: 'api-method--get', + POST: 'api-method--post', + PUT: 'api-method--put', + PATCH: 'api-method--patch', + DELETE: 'api-method--delete', +}; + +export default function Endpoint({method, path, baseUrls}: Props) { + const urls = baseUrls && baseUrls.length > 0 ? baseUrls : ['https://api.rownd.io']; + return ( +
    +
    + {method} + {path} +
    + {urls.length > 0 && ( +
    + {urls.map((u, idx) => ( + + {u} + {idx < urls.length - 1 ? : null} + + ))} +
    + )} +
    + ); +} + + diff --git a/rownd-docusaurus/src/components/RowndMDX/Frame.tsx b/rownd-docusaurus/src/components/RowndMDX/Frame.tsx new file mode 100644 index 0000000..99ae313 --- /dev/null +++ b/rownd-docusaurus/src/components/RowndMDX/Frame.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +type Props = { + src: string; + title?: string; + height?: number | string; +}; + +export default function Frame({src, title, height = 400}: Props) { + return ( +