Skip to content

feat: setup stripe checkout & webhooks api#290

Merged
andostronaut merged 1 commit intomainfrom
develop
Nov 18, 2024
Merged

feat: setup stripe checkout & webhooks api#290
andostronaut merged 1 commit intomainfrom
develop

Conversation

@andostronaut
Copy link
Copy Markdown
Member

@andostronaut andostronaut commented Nov 18, 2024

This is an automated pull request for branch develop

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a SubsButton component for streamlined subscription actions.
    • Added Stripe checkout functionality with a new API handler.
  • Configuration Updates

    • Expanded environment variables for Stripe integration.
    • Updated configuration to include new Stripe keys.
  • Improvements

    • Enhanced the Plans component to utilize the new SubsButton.
    • Updated the Plan type to include a price_id property for better data handling.
  • Bug Fixes

    • Renamed existing environment variables for clarity and consistency.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 18, 2024

Walkthrough

The pull request introduces several modifications primarily focused on environment variables and the integration of Stripe services. New variables are added to the .env.example file, including NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, STRIPE_SECRET_KEY, and STRIPE_WEBHOOK_SECRET, while renaming WEBHOOK_SECRET to CLERK_WEBHOOK_SECRET. The next.config.mjs file is updated to include STRIPE_SECRET_KEY. Additionally, new dependencies are added in package.json, and several API routes are modified to accommodate these changes, including the introduction of a new SubsButton component for handling subscriptions.

Changes

File Change Summary
.env.example Added variables: NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, CLERK_WEBHOOK_SECRET, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, CRYPTO_PASSPHRASE. Renamed WEBHOOK_SECRET to CLERK_WEBHOOK_SECRET.
next.config.mjs Added environment variable: STRIPE_SECRET_KEY.
package.json Added dependencies: @stripe/stripe-js (^4.10.0), stripe (^17.3.1).
src/app/api/clerk/webhooks/route.ts Renamed variable: WEBHOOK_SECRET to CLERK_WEBHOOK_SECRET. Updated webhook handling logic.
src/app/api/stripe/checkout/route.ts Added new POST handler for creating a checkout session.
src/app/api/stripe/webhooks/route.ts Modified POST function to include STRIPE_WEBHOOK_SECRET and updated request handling logic.
src/components/plans.tsx Updated imports and replaced Link and Button with SubsButton for subscription actions.
src/components/subs-button.tsx Introduced new SubsButton component for handling Stripe checkout sessions.
src/env.d.ts Added new environment variables: NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET. Renamed WEBHOOK_SECRET to CLERK_WEBHOOK_SECRET.
src/lib/definitions.ts Added property: price_id to the Plan type.
src/lib/stripe.ts Added initializeStripe function and created a Stripe instance with STRIPE_SECRET_KEY.

Possibly related PRs

🐰 In the land of code where bunnies hop,
New keys and secrets, we add to the crop.
With Stripe in our pouch, and plans that delight,
The SubsButton is ready, oh what a sight!
So let’s celebrate changes with joy and with cheer,
For our app is now better, the future is near! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Outside diff range and nitpick comments (14)
next.config.mjs (1)

Line range hint 1-8: Consider adding runtime validation for required environment variables.

To prevent runtime issues, it would be beneficial to validate the presence of required environment variables during startup.

Here's a suggested implementation:

 /** @type {import('next').NextConfig} */
+const requiredEnvVars = [
+  'CRYPTO_PASSPHRASE',
+  'POCKETBASE_URL',
+  'STRIPE_SECRET_KEY'
+];
+
+// Validate required env vars
+for (const envVar of requiredEnvVars) {
+  if (!process.env[envVar]) {
+    throw new Error(`Missing required environment variable: ${envVar}`);
+  }
+}
+
 const nextConfig = {
   env: {
     CRYPTO_PASSPHRASE: process.env.CRYPTO_PASSPHRASE,
     POCKETBASE_URL: process.env.POCKETBASE_URL,
     STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY
   }
 }
.env.example (2)

6-6: Document Stripe configuration requirements

Since this PR introduces Stripe integration, it would be helpful to add comments explaining:

  • Where to obtain these Stripe keys
  • Required Stripe account configuration
  • Any specific webhook endpoint configuration needed

Example documentation to add:

+# Get these from your Stripe Dashboard (https://dashboard.stripe.com/apikeys)
 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=""
 
+# Stripe Secret Key (keep this secure!)
 STRIPE_SECRET_KEY=""
 
+# Configure in Stripe Dashboard > Developers > Webhooks
+# Endpoint should be: https://your-domain/api/stripe/webhooks
 STRIPE_WEBHOOK_SECRET=""

Also applies to: 11-12


6-12: Consider adding validation for required environment variables

To prevent runtime issues, consider implementing environment variable validation at startup to ensure all required variables are properly set. This is particularly important for the newly added Stripe and crypto configurations.

Would you like me to help create a validation utility for these environment variables?

src/env.d.ts (1)

Line range hint 1-19: Consider adding validation constraints for environment variables.

While the type declarations are correct, consider enhancing type safety by adding validation constraints (e.g., using zod) to ensure these environment variables are properly set at runtime.

Example implementation:

import { z } from 'zod'

export const envSchema = z.object({
  NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().startsWith('pk_'),
  STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
  STRIPE_WEBHOOK_SECRET: z.string().startsWith('whsec_'),
  // ... other env vars
})

declare global {
  namespace NodeJS {
    interface ProcessEnv extends z.infer<typeof envSchema> {}
  }
}
src/app/api/stripe/webhooks/route.ts (1)

6-10: Enhance environment variable validation

While the basic validation is good, consider these improvements for better error handling and security:

  1. Validate the secret's format (should be 'whsec_' prefix for Stripe webhook secrets)
  2. Move environment validation to startup time
-  const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET
-
-  if (!STRIPE_WEBHOOK_SECRET) {
-    throw new Error('Please add STRIPE_WEBHOOK_SECRET from Stripe Dashboard to .env')
-  }
+  const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET
+
+  if (!STRIPE_WEBHOOK_SECRET || !STRIPE_WEBHOOK_SECRET.startsWith('whsec_')) {
+    throw new Error('Invalid STRIPE_WEBHOOK_SECRET. Please add a valid webhook secret from Stripe Dashboard to .env')
+  }
src/app/api/stripe/checkout/route.ts (1)

1-1: Consider adding type safety and error handling imports.

For better type safety and error handling in a Next.js API route:

+import { NextResponse } from 'next/server'
+import Stripe from 'stripe'
 import { stripe } from '@/lib/stripe'
src/components/subs-button.tsx (2)

10-11: Add prop validation and loading state.

Consider adding validation for the priceId and handling the loading state while waiting for userId.

+import { useEffect, useState } from 'react'
 import { useAuth } from '@clerk/nextjs'

-export const SubsButton = ({ priceId }: { priceId: string }) => {
+export const SubsButton = ({ priceId }: { priceId: string }) => {
+  const [isLoading, setIsLoading] = useState(false)
   const { userId } = useAuth()
+
+  useEffect(() => {
+    if (!priceId) {
+      console.error('Price ID is required')
+    }
+  }, [priceId])

28-32: Enhance button UI states and accessibility.

The button should provide visual feedback during loading and include proper accessibility attributes.

   return (
     <Button
       onClick={handleSubmit}
-      className='w-full'
+      className='w-full'
+      disabled={isLoading || !userId}
+      aria-busy={isLoading}
     >
-      Get Started
+      {isLoading ? 'Processing...' : 'Subscribe Now'}
     </Button>
   )
package.json (1)

32-32: Consider these architectural recommendations for Stripe integration

Since you're setting up Stripe checkout and webhooks, consider implementing:

  1. Proper error handling with retry mechanisms for failed payments
  2. Webhook signature verification using stripe.webhooks.constructEvent
  3. Idempotency keys for all POST requests to prevent duplicate charges
  4. Environment-specific configurations for test/live modes
  5. Webhook retry handling with proper response codes

Would you like me to provide example code for any of these implementations?

Also applies to: 51-51

src/app/api/clerk/webhooks/route.ts (3)

9-12: Consider adding type safety for environment variables

The environment variable validation is good, but consider using a schema validation library like zod to ensure type safety and comprehensive validation of all environment variables at startup.


Line range hint 45-54: Add error handling and use transactions for user creation flow

The user creation handler performs multiple database operations without proper error handling or transactional integrity:

  1. Creating an activity log
  2. Fetching the free plan
  3. Creating a subscription

This could lead to inconsistent data if any operation fails.

Consider refactoring to:

  if (evt.type === 'user.created') {
+   try {
+     await pocketbase.collection('activities').create(activity, { requestKey: null })
+     const freePlan = await pocketbase
+       .collection('plans')
+       .getFirstListItem('', { filter: `type = "free"`, requestKey: null })
+     await pocketbase.collection('subs').create(
+       { user_id: evt.data.id, plan_id: freePlan.id },
+       { requestKey: null }
+     )
+   } catch (error) {
+     console.error('Error in user creation flow:', error)
+     return new Response('Error processing user creation', { status: 500 })
+   }
-     pocketbase.collection('activities').create(activity, { requestKey: null })
-     pocketbase
-       .collection('plans')
-       .getFirstListItem('', { filter: `type = "free"`, requestKey: null })
-       .then((data) => {
-         const planId = data.id
-         const sub = { user_id: evt.data.id, plan_id: planId }
-         pocketbase.collection('subs').create(sub, { requestKey: null })
-       })
  }

Line range hint 56-82: Refactor duplicate activity logging logic

The activity logging code is duplicated across all event handlers. This violates the DRY principle and makes maintenance harder.

Consider extracting the common logic:

+ async function logActivity(type: string, description: string, userId: string, userAgent: string | null) {
+   try {
+     await pocketbase.collection('activities').create({
+       type,
+       description,
+       user_id: userId,
+       device: getDeviceType(userAgent || '')
+     }, { requestKey: null })
+   } catch (error) {
+     console.error(`Error logging activity ${type}:`, error)
+     throw error
+   }
+ }

  if (evt.type === 'session.created') {
-   const activity = {
-     type: 'login',
-     description: 'Account logged in',
-     user_id: evt.data.user_id,
-     device: getDeviceType(req.headers.get('user-agent') || '')
-   }
-   pocketbase.collection('activities').create(activity, { requestKey: null })
+   await logActivity('login', 'Account logged in', evt.data.user_id, req.headers.get('user-agent'))
  }
src/components/plans.tsx (1)

Line range hint 20-31: Consider caching plan data to improve performance.

The plans are fetched on every component mount. Since plan data doesn't change frequently, consider implementing caching or moving the fetch logic to a higher level (e.g., page level) to avoid unnecessary requests.

Example implementation using React Query:

import { useQuery } from '@tanstack/react-query'

const usePlans = () => {
  return useQuery({
    queryKey: ['plans'],
    queryFn: () => pocketbase.collection('plans').getList(1, 3),
    staleTime: 1000 * 60 * 5, // Consider data fresh for 5 minutes
  })
}
src/lib/definitions.ts (1)

157-157: Consider documenting the relationship between price and price_id

The addition of price_id for Stripe integration is good. However, having both price and price_id in the Plan type could be confusing:

  • price: Numeric value (presumably display price)
  • price_id: Stripe's price identifier

Consider either:

  1. Adding JSDoc comments to clarify the purpose of each field
  2. Removing the price field if it's redundant with Stripe's pricing

Example documentation:

 export type Plan = {
   // ... other fields ...
   /** Display price in smallest currency unit (e.g., cents) */
   price: number
   /** Stripe Price ID used for checkout */
   price_id: string
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 274be33 and e522574.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .env.example (1 hunks)
  • next.config.mjs (1 hunks)
  • package.json (2 hunks)
  • src/app/api/clerk/webhooks/route.ts (2 hunks)
  • src/app/api/stripe/checkout/route.ts (1 hunks)
  • src/app/api/stripe/webhooks/route.ts (1 hunks)
  • src/components/plans.tsx (2 hunks)
  • src/components/subs-button.tsx (1 hunks)
  • src/env.d.ts (1 hunks)
  • src/lib/definitions.ts (1 hunks)
  • src/lib/stripe.ts (1 hunks)
🔇 Additional comments (17)
next.config.mjs (1)

5-6: LGTM! Environment variable addition looks good.

The syntax is correct and the sensitive STRIPE_SECRET_KEY is properly handled without the NEXT_PUBLIC_ prefix.

src/lib/stripe.ts (1)

1-2: LGTM! Imports are correctly structured.

The imports appropriately separate client-side (@stripe/stripe-js) and server-side (stripe) SDK requirements.

.env.example (1)

10-10: Add security requirements for CRYPTO_PASSPHRASE

The crypto passphrase appears to be used for encryption/decryption. Please document:

  • Minimum length requirements
  • Complexity requirements
  • Any specific format requirements
✅ Verification successful

Let me check the encryption implementation to understand the specific requirements.


Let me also check the decryption implementation to get a complete picture.


Document AES encryption passphrase requirements in .env.example

Based on the implementation using CryptoJS AES in CBC mode:

  • Minimum length: 32 characters (256-bit key strength recommended for AES)
  • Complexity: Should contain a mix of uppercase, lowercase, numbers, and special characters
  • Format: UTF-8 encoded string

Example comment to add:

# AES encryption key - must be at least 32 characters with mixed case, numbers and special chars
CRYPTO_PASSPHRASE=""
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for crypto passphrase usage to understand the requirements
rg -l "CRYPTO_PASSPHRASE" | xargs rg -A 5 "CRYPTO_PASSPHRASE"

Length of output: 867


Script:

#!/bin/bash
# Search for the complete encryption implementation
ast-grep --pattern 'export const encrypt = ($$$) => {
  $$$
}'

Length of output: 738


Script:

#!/bin/bash
# Search for the complete decryption implementation
ast-grep --pattern 'export const decrypt = ($$$) => {
  $$$
}'

Length of output: 913

src/env.d.ts (3)

7-7: LGTM! Proper declaration of Stripe's public key.

The public key declaration follows Stripe's recommended naming convention and is correctly marked as a public variable with the NEXT_PUBLIC_ prefix.


10-10: LGTM! Clear naming for Clerk's webhook secret.

The rename from WEBHOOK_SECRET to CLERK_WEBHOOK_SECRET improves clarity by explicitly indicating its association with Clerk.


13-14: Verify Stripe secret handling in the application.

The type declarations for Stripe's sensitive keys are correct. However, let's verify that these secrets are properly handled in the application code.

✅ Verification successful

Let me gather more information about the Stripe secret key usage.


Let me check the actual implementation of the Stripe-related files to ensure proper secret handling.


Stripe secrets are properly handled in the application

The verification shows that:

  • Stripe secret key is only used server-side in src/lib/stripe.ts for initializing the Stripe client
  • Client-side code only uses the publishable key via NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
  • Webhook secret is properly used for signature verification in the webhook handler
  • All sensitive operations (checkout, webhooks) are handled in server-side API routes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential exposure of Stripe secrets in client-side code
# Expected: No occurrences of direct secret usage in client components

# Check for any direct references to STRIPE_SECRET_KEY in client-side code
echo "Checking for Stripe secret key usage in client components..."
rg -g "src/**/*(page|component|client).{ts,tsx}" "STRIPE_SECRET_KEY"

# Check for proper usage of Stripe secret key in server-side code
echo "Verifying Stripe secret key usage in server components..."
rg -g "src/**/*(api|server).{ts,tsx}" "STRIPE_SECRET_KEY"

# Check for webhook secret usage
echo "Checking webhook secret handling..."
rg -g "src/**/api/**" "STRIPE_WEBHOOK_SECRET"

Length of output: 1229


Script:

#!/bin/bash
# Search for Stripe secret key usage in all files
echo "Checking Stripe secret key usage across the codebase..."
rg "STRIPE_SECRET_KEY" -A 3

# Check for Stripe initialization
echo "Checking Stripe initialization..."
rg "new Stripe" -A 3

# Check for stripe import patterns
echo "Checking stripe import patterns..."
rg "import.*stripe" -i

Length of output: 1116


Script:

#!/bin/bash
# Check the stripe library implementation
echo "Checking stripe library implementation..."
cat src/lib/stripe.ts

# Check the webhook implementation
echo "Checking webhook implementation..."
cat src/app/api/stripe/webhooks/route.ts

# Check checkout implementation
echo "Checking checkout implementation..."
cat src/app/api/stripe/checkout/route.ts

Length of output: 2031

src/app/api/stripe/webhooks/route.ts (2)

1-20: Verify security configuration for Stripe integration

Let's ensure all necessary security configurations are in place for the Stripe integration.

#!/bin/bash
# Description: Verify security configurations for Stripe integration
# Expected: Should find proper CORS, rate limiting, and environment configurations

# Check for CORS configuration
rg -l "cors" --type ts

# Check for rate limiting implementation
rg -l "rate.*limit" --type ts

# Verify environment variable definitions
cat .env.example | grep STRIPE

1-3: Verify stripe singleton initialization

The stripe import suggests a singleton pattern. Let's verify the initialization to ensure proper error handling and configuration.

✅ Verification successful

Let me try a different approach to verify the stripe singleton initialization.


Stripe singleton initialization is properly implemented

The stripe singleton is correctly initialized using the STRIPE_SECRET_KEY environment variable, and the code also includes a separate client-side initialization using NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY. The implementation follows Stripe's best practices with proper environment variable usage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify stripe singleton initialization
# Expected: Should find proper initialization with error handling

# Check stripe singleton implementation
ast-grep --pattern 'export const stripe = $$$'

Length of output: 171


Script:

#!/bin/bash
# Search for stripe initialization in lib directory
fd stripe lib --type f --exec cat {}

# Fallback: Search for stripe initialization in src directory
fd stripe src --type f --exec cat {}

Length of output: 435

src/components/subs-button.tsx (2)

1-8: LGTM! Imports are well-organized and necessary.

The imports cover all required dependencies for authentication, HTTP requests, UI components, and Stripe integration.


8-8: Verify Stripe initialization and environment setup.

Ensure that the Stripe initialization is properly configured and environment variables are set up correctly.

✅ Verification successful

Stripe initialization and environment variables are properly configured

The verification shows:

  • initializeStripe function is correctly implemented in src/lib/stripe.ts using the public key
  • Both NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY and STRIPE_SECRET_KEY are:
    • Properly typed in src/env.d.ts
    • Correctly used in the codebase
    • Configured in next.config.mjs
  • Stripe instance is properly initialized with the secret key
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for proper Stripe initialization and environment variable usage

# Look for Stripe initialization implementation
echo "Checking Stripe initialization..."
ast-grep --pattern 'export const initializeStripe = async () => {
  $$$
}'

# Verify environment variable usage
echo "Checking environment variable usage..."
rg "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY|STRIPE_SECRET_KEY" -A 3

Length of output: 1131

package.json (2)

32-32: Verify @stripe/stripe-js version compatibility

The specified version ^4.10.0 appears incorrect as the latest stable version is 2.4.0. This might cause compatibility issues.

#!/bin/bash
# Description: Verify @stripe/stripe-js version compatibility and check for breaking changes

# Check NPM for latest versions and release info
npm view @stripe/stripe-js versions --json | jq -r '.[]' | tail -n 5
npm view @stripe/stripe-js time --json | jq '.modified,.created'

# Check for related issues or discussions
gh search issues --repo kinotio/drowser-studio "stripe-js version" --json title,url

51-51: Verify stripe package version compatibility

The specified version ^17.3.1 appears incorrect as the latest stable version is 14.12.0. This might cause compatibility issues.

src/app/api/clerk/webhooks/route.ts (2)

29-29: LGTM: Webhook verification setup is secure

The webhook verification is properly implemented using the Svix library with the correct secret.


9-9: Verify environment variable configuration

Ensure that the CLERK_WEBHOOK_SECRET is properly configured in all environment files and that there are no remaining references to the old WEBHOOK_SECRET name.

✅ Verification successful

Let me modify the search pattern and try again to verify the webhook secret configuration.


Let me try one final search focusing on the TypeScript files and any files that might contain environment configurations.


Environment variable configuration is correctly implemented

The codebase shows consistent usage of CLERK_WEBHOOK_SECRET:

  • It's properly typed in src/env.d.ts
  • It's correctly used in src/app/api/clerk/webhooks/route.ts
  • No instances of the old WEBHOOK_SECRET name were found
  • The naming follows the same pattern as other webhook secrets (e.g., STRIPE_WEBHOOK_SECRET)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old webhook secret name
echo "Checking for old webhook secret references..."
rg "WEBHOOK_SECRET(?!.*CLERK)" --type ts --type env

# Verify environment variable configuration
echo "Checking environment variable configuration..."
for env_file in $(fd -e .env -e .env.example -e .env.local -e .env.development); do
  echo "Checking $env_file..."
  grep -E "CLERK_WEBHOOK_SECRET|WEBHOOK_SECRET" "$env_file" || true
done

Length of output: 564


Script:

#!/bin/bash
# Search for any webhook secret references
echo "Checking webhook secret references..."
rg "WEBHOOK_SECRET" --type ts --type env -l

# List all environment files
echo -e "\nListing environment files..."
fd -e .env -e .env.example -e .env.local -e .env.development

# Check content of environment example files
echo -e "\nChecking environment example files..."
fd -e .env.example -e .env.sample -e .env.template -x cat {}

Length of output: 448


Script:

#!/bin/bash
# Search for webhook secret references in TypeScript files
echo "Checking webhook secret references in TypeScript files..."
rg "WEBHOOK_SECRET" --type ts -A 2

# Find and check content of any potential environment files
echo -e "\nChecking for environment files (including hidden)..."
find . -maxdepth 2 -type f -name "*.env*" -o -name ".env*" -o -name "env.*" 2>/dev/null

# Search for environment-related patterns in common config files
echo -e "\nChecking config files for environment variables..."
rg "WEBHOOK_SECRET|CLERK.*SECRET" -g "*.{json,yaml,yml,config.js,config.ts}"

Length of output: 2038

src/components/plans.tsx (2)

75-75: Consider enhancing error handling and loading state for subscription flow.

The SubsButton integration is a critical change for the Stripe checkout flow. While the implementation looks correct, consider these improvements:

  1. Add error boundaries or error handling for failed Stripe interactions
  2. Include loading states during checkout initialization
  3. Consider adding a confirmation step for higher-priced plans
#!/bin/bash
# Description: Verify SubsButton implementation for proper error handling

# Check SubsButton implementation
echo "Checking SubsButton implementation..."
ast-grep --pattern 'export function SubsButton({ priceId }: { priceId: string }) {
  $$$
}'

# Look for error handling patterns
echo "Checking error handling patterns..."
rg -A 5 "try.*catch" "src/components/subs-button.tsx"

# Check for loading state implementation
echo "Checking loading state..."
rg -A 5 "useState.*loading|isLoading" "src/components/subs-button.tsx"

14-15: Verify path alias configuration.

The import statements use the @components alias. While this is a good practice for maintainability, ensure the path alias is properly configured in your TypeScript/JavaScript config.

✅ Verification successful

Path alias configuration is correctly set up

The @components path alias is properly configured in tsconfig.json and maps to ./src/components/*. Both imported components exist at their expected locations:

  • @components/ui/skeletonsrc/components/ui/skeleton.tsx
  • @components/subs-buttonsrc/components/subs-button.tsx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify path alias configuration
# Expected: Find tsconfig.json or jsconfig.json with path aliases defined

# Search for config files
echo "Searching for TypeScript/JavaScript config files..."
fd -e json -e jsonc "tsconfig|jsconfig"

# If found, check for path aliases
for config in $(fd -e json -e jsonc "tsconfig|jsconfig"); do
  echo "Checking path aliases in $config..."
  cat "$config" | jq '.compilerOptions.paths'
done

Length of output: 445


Script:

#!/bin/bash
# Let's try a different approach to verify the path alias configuration

# Check for Next.js config which commonly defines path aliases
echo "Checking Next.js config..."
if [ -f "next.config.js" ]; then
    cat next.config.js
fi

# Check for vite config which might define aliases
echo -e "\nChecking Vite config..."
fd -e js -e ts "vite.config"

# Look for actual usage of @components alias
echo -e "\nChecking @components alias usage..."
rg "@components/" -l

# Check if the components directory exists
echo -e "\nVerifying components directory structure..."
fd -t d "components$"

Length of output: 496


Script:

#!/bin/bash
# Let's check the tsconfig.json since we found it contains @components references
echo "Checking tsconfig.json content..."
cat tsconfig.json

# Also check if the imported components exist
echo -e "\nVerifying imported components existence..."
fd "skeleton.tsx|subs-button.tsx" src/components

Length of output: 1036

src/lib/definitions.ts (1)

157-157: Verify Plan type usage across the codebase

Since price_id is a required field, we should verify that all instances where Plan objects are created include this new field.

✅ Verification successful

All usages of Plan type are consistent with the new price_id field

Based on the code analysis:

  • The Plan type is used in plans.tsx where price_id is correctly used in the SubsButton component
  • In subs.tsx, the Plan is only used for displaying the plan name
  • The data is fetched from the PocketBase backend, which ensures the Plan objects are properly populated
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of Plan type and verify price_id field usage

# Find direct Plan type usage
echo "=== Direct Plan type usage ==="
rg "Plan(\[?\]|{)" -A 5

# Find object literals that might be Plans
echo -e "\n=== Potential Plan object literals ==="
rg "price.*number.*type.*string|type.*string.*price.*number" -A 10

Length of output: 358


Script:

#!/bin/bash
# Let's try a different approach to find Plan type usage

# Find Plan type definition and its usage
echo "=== Plan type definition and usage ==="
rg "type Plan" -A 5

# Find files importing or using Plan type
echo -e "\n=== Files importing/using Plan ==="
rg "Plan" --type typescript

# Find potential price_id usage
echo -e "\n=== price_id usage ==="
rg "price_id" --type typescript -A 2

Length of output: 655


Script:

#!/bin/bash
# Let's try without type specification

# Find Plan references
echo "=== Plan references ==="
rg "Plan" -l

# Find price_id usage
echo -e "\n=== price_id usage ==="
rg "price_id"

# Find object literals that might be Plan instances
echo -e "\n=== Potential Plan object creation ==="
rg "{(\s|\n)*collectionId.*(\s|\n)*collectionName" -A 10

Length of output: 637


Script:

#!/bin/bash
# Let's examine the files that reference Plan

echo "=== Content of plans.tsx ==="
cat src/components/plans.tsx

echo -e "\n=== Content of subs.tsx ==="
cat src/components/subs.tsx

echo -e "\n=== Content of page.tsx ==="
cat src/app/\(root\)/page.tsx

Length of output: 7208

Comment thread src/lib/stripe.ts
Comment thread src/lib/stripe.ts
Comment thread src/lib/stripe.ts
Comment thread src/app/api/stripe/webhooks/route.ts
Comment thread src/app/api/stripe/webhooks/route.ts
Comment thread src/app/api/stripe/checkout/route.ts
Comment thread src/app/api/stripe/checkout/route.ts
Comment thread src/app/api/stripe/checkout/route.ts
Comment thread src/app/api/stripe/checkout/route.ts
Comment thread src/components/subs-button.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant