feat: setup stripe checkout & webhooks api#290
Conversation
WalkthroughThe pull request introduces several modifications primarily focused on environment variables and the integration of Stripe services. New variables are added to the Changes
Possibly related PRs
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
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 requirementsSince 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 variablesTo 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 validationWhile the basic validation is good, consider these improvements for better error handling and security:
- Validate the secret's format (should be 'whsec_' prefix for Stripe webhook secrets)
- 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
priceIdand handling the loading state while waiting foruserId.+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 integrationSince you're setting up Stripe checkout and webhooks, consider implementing:
- Proper error handling with retry mechanisms for failed payments
- Webhook signature verification using
stripe.webhooks.constructEvent- Idempotency keys for all POST requests to prevent duplicate charges
- Environment-specific configurations for test/live modes
- 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 variablesThe environment variable validation is good, but consider using a schema validation library like
zodto 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 flowThe user creation handler performs multiple database operations without proper error handling or transactional integrity:
- Creating an activity log
- Fetching the free plan
- 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 logicThe 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 betweenpriceandprice_idThe addition of
price_idfor Stripe integration is good. However, having bothpriceandprice_idin thePlantype could be confusing:
price: Numeric value (presumably display price)price_id: Stripe's price identifierConsider either:
- Adding JSDoc comments to clarify the purpose of each field
- Removing the
pricefield if it's redundant with Stripe's pricingExample 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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.tsfor 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 STRIPE1-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:
initializeStripefunction is correctly implemented insrc/lib/stripe.tsusing the public key- Both
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYandSTRIPE_SECRET_KEYare:- Properly typed in
src/env.d.ts - Correctly used in the codebase
- Configured in
next.config.mjs
- Properly typed in
- 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,url51-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_SECRETname 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:
- Add error boundaries or error handling for failed Stripe interactions
- Include loading states during checkout initialization
- 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/skeleton→src/components/ui/skeleton.tsx@components/subs-button→src/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.tsxwhereprice_idis correctly used in theSubsButtoncomponent - 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
This is an automated pull request for branch develop
Summary by CodeRabbit
Release Notes
New Features
SubsButtoncomponent for streamlined subscription actions.Configuration Updates
Improvements
Planscomponent to utilize the newSubsButton.Plantype to include aprice_idproperty for better data handling.Bug Fixes