### Install elysia-clerk with Bun Source: https://github.com/wobsoriano/elysia-clerk/blob/main/README.md Installs the elysia-clerk package using the Bun package manager. This is the primary method for adding the plugin to your project. ```bash bun add elysia-clerk ``` -------------------------------- ### Add Frontend API to Elysia Script (JavaScript) Source: https://github.com/wobsoriano/elysia-clerk/blob/main/dev/index.html This instruction guides the user to add the necessary Frontend API configuration to the top of their `src/script.js` file. This is crucial for the application to function correctly with Clerk authentication. ```javascript // Add Frontend API configuration here // Example: import './clerk.js'; // Ensure this is at the top of src/script.js ``` -------------------------------- ### Integrate Elysia Clerk Plugin in Elysia Application Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt This TypeScript example shows the basic integration of the Elysia Clerk plugin into an Elysia application. The plugin automatically reads configuration from environment variables. It then defines a '/health' route that checks for user authentication status. ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' // Plugin automatically reads from environment const app = new Elysia() .use(clerkPlugin()) .get('/health', ({ auth }) => ({ authenticated: !!auth().userId, timestamp: new Date().toISOString(), })) .listen(3000) console.log('Server running on http://localhost:3000') ``` -------------------------------- ### Access Clerk Backend Client with Elysia Decorator Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt The `clerk` decorator in `elysia-clerk` provides access to Clerk's backend client within Elysia routes. It allows fetching users, managing organizations, and handling invitations by exposing methods from `@clerk/backend`. Ensure `elysia-clerk` is installed and configured. ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' const app = new Elysia() .use(clerkPlugin()) .get('/user/:id', async ({ clerk, params, error }) => { try { const user = await clerk.users.getUser(params.id) return { id: user.id, email: user.emailAddresses[0]?.emailAddress, firstName: user.firstName, lastName: user.lastName, imageUrl: user.imageUrl, createdAt: user.createdAt, } } catch (err) { return error(404, { error: 'User not found' }) } }) .get('/users', async ({ clerk, query }) => { // List users with pagination const users = await clerk.users.getUserList({ limit: Number(query.limit) || 10, offset: Number(query.offset) || 0, }) return { users: users.data, totalCount: users.totalCount } }) .patch('/user/:id', async ({ clerk, params, body, auth, error }) => { const { userId } = auth() if (!userId) return error(401) // Update user metadata const updatedUser = await clerk.users.updateUser(params.id, { firstName: body.firstName, lastName: body.lastName, publicMetadata: body.metadata, }) return { user: updatedUser } }) .delete('/user/:id/sessions', async ({ clerk, params }) => { // Revoke all sessions for a user const sessions = await clerk.sessions.getSessionList({ userId: params.id }) for (const session of sessions.data) { await clerk.sessions.revokeSession(session.id) } return { revoked: sessions.data.length } }) .listen(3000) ``` -------------------------------- ### Import Lato Font and Apply Global Styles (CSS) Source: https://github.com/wobsoriano/elysia-clerk/blob/main/dev/index.html This snippet imports the Lato font from Google Fonts and applies it as the default font family for HTML and body elements. It also centers text and styles specific UI elements like the user button and authentication links. ```css /* Import Lato font */ @import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap'); /* Apply global styles */ html, body { font-family: 'Lato', sans-serif; text-align: center; } /* Style user button */ #user-button { margin: auto; } /* Hide auth links by default */ #auth-links { display: none; } /* Style warning messages */ #no-frontend-api-warning h3 { color: #e61d1d; margin-bottom: 0; } #no-frontend-api-warning h4 { color: #333; font-weight: 400; margin-top: 10px; } ``` -------------------------------- ### Configure Elysia Clerk Plugin with Environment Variables Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt This snippet demonstrates how to configure the Elysia Clerk plugin by reading necessary keys and optional settings from environment variables. Ensure CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY are set for basic functionality. Optional variables allow customization of API endpoints and telemetry. ```bash # Required: Get these from https://dashboard.clerk.com/last-active?path=api-keys CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx CLERK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Required for webhook verification CLERK_WEBHOOK_SIGNING_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Optional: Custom configuration CLERK_API_URL=https://api.clerk.com # Custom API endpoint CLERK_API_VERSION=v1 # API version CLERK_JWT_KEY=your-jwt-key # Custom JWT key # Optional: Telemetry settings CLERK_TELEMETRY_DISABLED=true # Disable telemetry CLERK_TELEMETRY_DEBUG=false # Enable telemetry debug mode ``` -------------------------------- ### Standalone Clerk Client Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt Demonstrates using the standalone Clerk backend client for background tasks or within Elysia routes without the plugin. ```APIDOC ## clerkClient - Standalone Backend Client ### Description A pre-configured Clerk backend client that can be imported directly without using the plugin. Useful for background jobs, scripts, or contexts outside of HTTP request handlers. Automatically reads configuration from environment variables. ### Usage Example (Background Job) ```typescript import { clerkClient } from 'elysia-clerk' async function syncUsers() { const users = await clerkClient.users.getUserList({ limit: 100 }) for (const user of users.data) { console.log(`Processing user: ${user.id}`) // Sync to external system } return { processed: users.data.length } } ``` ### Usage Example (Elysia Route) ```typescript import { Elysia } from 'elysia' import { clerkPlugin, clerkClient } from 'elysia-clerk' const app = new Elysia() .use(clerkPlugin()) .get('/admin/users', async () => { // Can use standalone client directly const users = await clerkClient.users.getUserList({ orderBy: '-created_at', limit: 50, }) return users.data }) .listen(3000) ``` ``` -------------------------------- ### Webhook Verification Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt Securely verify incoming Clerk webhooks using the re-exported `verifyWebhook` helper. ```APIDOC ## verifyWebhook - Webhook Verification ### Description Re-exported webhook verification helper from `@clerk/backend/webhooks` for securely processing Clerk webhook events. Requires `CLERK_WEBHOOK_SIGNING_SECRET` environment variable. Validates webhook signatures to ensure events are genuinely from Clerk. ### Method POST ### Endpoint /webhook/clerk ### Parameters #### Request Body - **request** (Request) - The incoming HTTP request object containing the webhook payload and signature. ### Request Example (The request body is the raw webhook payload, signature is typically in headers) ### Response #### Success Response (200) - **received** (boolean) - Indicates that the webhook was successfully processed. #### Error Response (400) - Returns a 400 status code if webhook verification fails. #### Response Example (Success) { "received": true } ### Usage Example ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' import { verifyWebhook } from 'elysia-clerk/webhooks' // Set CLERK_WEBHOOK_SIGNING_SECRET in your environment const app = new Elysia() .use(clerkPlugin()) .post('/webhook/clerk', async ({ request }) => { try { const evt = await verifyWebhook(request) // Handle different event types switch (evt.type) { case 'user.created': console.log('New user:', evt.data.id) // Create user in your database break // ... other event types } return { received: true } } catch (err) { console.error('Webhook verification failed:', err) return new Response('Webhook verification failed', { status: 400 }) } }) .listen(3000) ``` ``` -------------------------------- ### Elysia with Clerk Plugin Usage Source: https://github.com/wobsoriano/elysia-clerk/blob/main/README.md Demonstrates how to use the elysia-clerk plugin within an Elysia application. It configures the plugin, accesses authentication state (userId), and retrieves user details using the Clerk client. ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' new Elysia() .use(clerkPlugin()) .get('/private', async ({ auth, clerk, error }) => { const { userId } = auth() /** * Access the auth state in the context. * See the AuthObject here https://clerk.com/docs/references/nextjs/auth-object#auth-object */ if (!userId) { return error(401) } /** * For other resource operations, you can use the clerk client from the context. * See what other utilities Clerk exposes here https://clerk.com/docs/references/backend/overview */ const user = await clerk.users.getUser(userId) return { user } }) .listen(3000) ``` -------------------------------- ### Use Standalone Clerk Backend Client Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt The `clerkClient` from `elysia-clerk` offers a pre-configured Clerk backend client usable outside of HTTP request handlers, such as in background jobs or scripts. It automatically reads configuration from environment variables. It can also be used alongside the `clerkPlugin` within Elysia routes. ```typescript import { clerkClient } from 'elysia-clerk' // Use in background jobs or scripts async function syncUsers() { const users = await clerkClient.users.getUserList({ limit: 100 }) for (const user of users.data) { console.log(`Processing user: ${user.id}`) // Sync to external system } return { processed: users.data.length } } // Use in Elysia routes alongside the plugin import { Elysia } from 'elysia' import { clerkPlugin, clerkClient } from 'elysia-clerk' const app = new Elysia() .use(clerkPlugin()) .get('/admin/users', async () => { // Can use standalone client directly const users = await clerkClient.users.getUserList({ orderBy: '-created_at', limit: 50, }) return users.data }) .listen(3000) ``` -------------------------------- ### Configure Clerk API Keys Source: https://github.com/wobsoriano/elysia-clerk/blob/main/README.md Sets the Clerk Publishable and Secret keys as environment variables. These keys are essential for the elysia-clerk plugin to authenticate requests and interact with the Clerk API. ```env CLERK_PUBLISHABLE_KEY=pk_******* CLERK_SECRET_KEY=sk_****** ``` -------------------------------- ### Initialize Clerk Authentication with Elysia Plugin Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt The main plugin function to add Clerk authentication to an Elysia application. It authenticates incoming requests using Clerk's backend SDK and provides access to auth state and the Clerk client in route handlers. Supports configuration options from AuthenticateRequestOptions. ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' // Basic setup with environment variables // Required: CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY in .env const app = new Elysia() .use(clerkPlugin()) .get('/public', () => { return { message: 'This is a public endpoint' } }) .get('/private', async ({ auth, clerk, error }) => { // auth() returns SessionAuthObject with userId, sessionId, etc. const { userId } = auth() if (!userId) { return error(401, 'Unauthorized') } // Use clerk client to fetch full user details const user = await clerk.users.getUser(userId) return { userId, email: user.emailAddresses[0]?.emailAddress, firstName: user.firstName, lastName: user.lastName } }) .listen(3000) // With custom options const appWithOptions = new Elysia() .use(clerkPlugin({ secretKey: 'sk_test_xxxxx', publishableKey: 'pk_test_xxxxx', // Additional AuthenticateRequestOptions authorizedParties: ['https://myapp.com'], jwtKey: 'custom-jwt-key', })) .get('/', ({ auth }) => ({ signedIn: !!auth().userId })) .listen(3000) ``` -------------------------------- ### User Management API Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt Endpoints for fetching, listing, updating, and revoking user sessions using the Clerk backend client within Elysia. ```APIDOC ## GET /user/:id ### Description Fetches a specific user by their ID. ### Method GET ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user. ### Response #### Success Response (200) - **id** (string) - The user's unique identifier. - **email** (string) - The user's primary email address. - **firstName** (string) - The user's first name. - **lastName** (string) - The user's last name. - **imageUrl** (string) - The URL of the user's profile image. - **createdAt** (Date) - The timestamp when the user was created. #### Response Example { "id": "user_123abc", "email": "test@example.com", "firstName": "John", "lastName": "Doe", "imageUrl": "https://example.com/image.jpg", "createdAt": "2023-10-27T10:00:00.000Z" } ## GET /users ### Description Retrieves a list of users with optional pagination. ### Method GET ### Endpoint /users ### Parameters #### Query Parameters - **limit** (number) - Optional - The maximum number of users to return (default: 10). - **offset** (number) - Optional - The number of users to skip (default: 0). ### Response #### Success Response (200) - **users** (array) - An array of user objects. - **totalCount** (number) - The total number of users available. #### Response Example { "users": [ { "id": "user_123abc", "email": "test@example.com", "firstName": "John", "lastName": "Doe", "imageUrl": "https://example.com/image.jpg", "createdAt": "2023-10-27T10:00:00.000Z" } ], "totalCount": 100 } ## PATCH /user/:id ### Description Updates a user's information, including first name, last name, and public metadata. ### Method PATCH ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user to update. #### Request Body - **firstName** (string) - Optional - The user's new first name. - **lastName** (string) - Optional - The user's new last name. - **metadata** (object) - Optional - Public metadata to associate with the user. ### Request Example { "firstName": "Jane", "lastName": "Doe", "metadata": { "role": "admin" } } ### Response #### Success Response (200) - **user** (object) - The updated user object. #### Response Example { "user": { "id": "user_123abc", "firstName": "Jane", "lastName": "Doe", "publicMetadata": { "role": "admin" } } } ## DELETE /user/:id/sessions ### Description Revokes all active sessions for a given user. ### Method DELETE ### Endpoint /user/:id/sessions ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user whose sessions should be revoked. ### Response #### Success Response (200) - **revoked** (number) - The number of sessions that were revoked. #### Response Example { "revoked": 5 } ``` -------------------------------- ### Verify Clerk Webhook Signatures Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt The `verifyWebhook` helper, re-exported from `@clerk/backend/webhooks`, securely processes Clerk webhook events by validating their signatures. It requires the `CLERK_WEBHOOK_SIGNING_SECRET` environment variable to be set. This ensures that incoming events are genuinely from Clerk. ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' import { verifyWebhook } from 'elysia-clerk/webhooks' // Set CLERK_WEBHOOK_SIGNING_SECRET in your environment const app = new Elysia() .use(clerkPlugin()) .post('/webhook/clerk', async ({ request }) => { try { const evt = await verifyWebhook(request) // Handle different event types switch (evt.type) { case 'user.created': console.log('New user:', evt.data.id) // Create user in your database await createUserInDB({ clerkId: evt.data.id, email: evt.data.email_addresses[0]?.email_address, firstName: evt.data.first_name, }) break case 'user.updated': console.log('User updated:', evt.data.id) // Update user in your database await updateUserInDB(evt.data.id, { email: evt.data.email_addresses[0]?.email_address, firstName: evt.data.first_name, }) break case 'user.deleted': console.log('User deleted:', evt.data.id) // Remove user from your database await deleteUserFromDB(evt.data.id) break case 'session.created': console.log('New session for user:', evt.data.user_id) break } return { received: true } } catch (err) { console.error('Webhook verification failed:', err) return new Response('Webhook verification failed', { status: 400 }) } }) .listen(3000) ``` -------------------------------- ### Access Authentication State with auth() in Elysia Source: https://context7.com/wobsoriano/elysia-clerk/llms.txt The auth() function is resolved on every request and returns a SessionAuthObject containing the authenticated user's session information, including userId, sessionId, and orgId. It returns null values when the user is not authenticated. ```typescript import { Elysia } from 'elysia' import { clerkPlugin } from 'elysia-clerk' const app = new Elysia() .use(clerkPlugin()) .get('/session-info', ({ auth }) => { const authObject = auth() // SessionAuthObject properties return { userId: authObject.userId, // string | null sessionId: authObject.sessionId, // string | null orgId: authObject.orgId, // string | null orgRole: authObject.orgRole, // string | null orgSlug: authObject.orgSlug, // string | null sessionClaims: authObject.sessionClaims, } }) .post('/protected-action', async ({ auth, error }) => { const { userId, orgId, orgRole } = auth() if (!userId) { return error(401, { error: 'Authentication required' }) } // Check organization membership if (!orgId) { return error(403, { error: 'Organization membership required' }) } // Check admin role if (orgRole !== 'admin') { return error(403, { error: 'Admin access required' }) } return { success: true, userId, orgId } }) .listen(3000) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.