Skip to content

added supabase migration file for youtube stats, added validation schemas#146

Open
GauravOP-03 wants to merge 2 commits intoscriptaiapp:mainfrom
GauravOP-03:supabase-validation
Open

added supabase migration file for youtube stats, added validation schemas#146
GauravOP-03 wants to merge 2 commits intoscriptaiapp:mainfrom
GauravOP-03:supabase-validation

Conversation

@GauravOP-03
Copy link
Copy Markdown
Collaborator

📝 Description

Introduce shared billing and YouTube stats schema between backend and frontend via @repo/validation, and add Supabase migrations + functions to enforce plan-based usage limits at the database layer. This PR wires up typed models and quota-aware SQL functions so that both the API and web app can consume the same schema for billing, channel analytics, and feature usage.

🎯 Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🎨 Style/UI changes (formatting, missing semi colons, etc; no logic change)
  • ♻️ Refactoring (no functional changes, code improvements)
  • ⚡ Performance improvements
  • 🧪 Adding or updating tests
  • 🔧 Configuration changes

🧪 Testing

  • I have tested my changes locally
  • I have added tests for my changes
  • All existing tests pass
  • I have tested on different browsers/devices (if applicable)

(Describe briefly what you ran, e.g. Supabase migration locally + key flows on dashboard.)

📋 Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (this PR description + internal docs)
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have checked my code and corrected any misspellings
  • I have read the Contributing Guide

📸 Screenshots (if applicable)

Before:
No shared billing/stats schema between backend and frontend; no plan-based quota functions in DB.

After:
Billing and YouTube stats types exported from @repo/validation; DB now exposes use_feature and get_feature_usage for plan-aware limits.

(You can add real UI screenshots here if you changed any dashboard pages.)

🔧 Technical Details

  • Shared schema for billing and usage

    • Added BillingTypes and YoutubeStatsTypes to @repo/validation and re-exported them from src/index.ts so both backend and frontend can import the same types.
    • BillingTypes models Plan, SubscriptionInfo, and BillingInfo in a way that matches our Stripe + Supabase billing domain.
    • YoutubeStatsTypes models YouTube channel/profile data plus analytics and quota-related fields (e.g. daily_limit, usage_count, remaining, cooldown_minutes, cooldown_remaining, can_use_now), which match what we now persist in Supabase and return from the stats endpoints.
  • Supabase package and CLI usage

    • Updated @repo/supabase package.json to be the central place for Supabase tooling:
      • supabase:dev, supabase:init, supabase:link, supabase:pull, supabase:push.
    • This follows current Supabase migration best practices (SQL-first, version-controlled migrations) so all environments use the same workflow.
  • Database schema changes (20260224185424_plans_v2.sql)

    • plans table:
      • Added daily_limit int NOT NULL DEFAULT 5 and cooldown_minutes int NOT NULL DEFAULT 60.
      • Purpose: attach usage policy directly to each plan so we can configure per-plan limits/cooldowns as data instead of hardcoding them in the application.
    • youtube_channels table:
      • Added analytics and usage fields:
        • top_videos jsonb, recent_videos jsonb, youtube_trained_videos jsonb.
        • last_synced_at timestamptz for when we last pulled stats from YouTube.
        • last_used_at timestamptz, usage_count int NOT NULL DEFAULT 0, usage_reset_date date NOT NULL DEFAULT CURRENT_DATE.
      • Purpose: persist channel analytics and track how many times a user has used a feature today, plus when they last used it, so we can enforce both a daily quota and a time-based cooldown inside the DB.
  • DB functions for feature usage

    • use_feature(p_user_id uuid) RETURNS json

      • What it does:
        • Resolves the user’s active plan by joining subscriptionsplans (with a fallback to the starter plan).
        • Reads usage state from youtube_channels (usage_count, last_used_at, usage_reset_date).
        • Resets usage if usage_reset_date is before today.
        • Enforces:
          • Cooldown: if time since last_used_at < cooldown_minutes, returns JSON with allowed: false, reason: 'cooldown', minutes_remaining, and plan info.
          • Daily limit: if usage_count >= daily_limit, returns JSON with allowed: false, reason: 'daily_limit', usage_count, daily_limit, remaining: 0.
        • On success, atomically updates youtube_channels:
          • If date rolled over, sets usage_count = 1, otherwise increments by 1.
          • Sets usage_reset_date = CURRENT_DATE and last_used_at = NOW().
        • Returns a JSON payload with:
          • allowed, plan, usage_count, remaining, daily_limit, cooldown_minutes, and a human-readable message.
      • Why:
        • Centralizes plan-based quota and cooldown logic into a single, database-level function.
        • Ensures atomic increments and correct behavior under high concurrency (no race conditions in application code).
        • Returns a structured JSON contract that both backend and frontend can rely on without duplicating business rules.
      • Benefits:
        • Consistent enforcement of limits across all callers (API, jobs, future services).
        • Safer at scale: DB enforces limits even with multiple app instances.
        • Simple integration: callers only need to check allowed and handle the returned reason/message.
    • get_feature_usage(p_user_id uuid) RETURNS json

      • What it does:
        • Resolves the user’s current plan the same way as use_feature.
        • Reads usage_count, last_used_at, usage_reset_date from youtube_channels.
        • Resets counts for today in-memory if usage_reset_date is null or before today.
        • Computes:
          • remaining = max(daily_limit - usage_count, 0).
          • cooldown_remaining in minutes based on cooldown_minutes and time since last_used_at.
          • can_use_now = (cooldown_remaining < 0.01) AND (usage_count < daily_limit).
        • Returns a JSON summary: plan, usage_count, remaining, daily_limit, cooldown_minutes, cooldown_remaining, can_use_now.
      • Why:
        • Provide a read-only, side-effect-free view of the user’s usage and remaining quota for dashboards and UI checks.
        • Avoid mutating state when we only need to show banners, disabled buttons, or stats.
      • Benefits:
        • Great UX: frontend can display “X of Y uses left” and live cooldown timers based on a single source of truth.
        • Clear separation: get_feature_usage is for reading, use_feature is for consuming quota.
  • Schema reuse across frontend and backend

    • Both the backend services and the React app import the same TypeScript types from @repo/validation for:
      • Billing (Plan, SubscriptionInfo, BillingInfo).
      • YouTube stats and feature usage (UserProfile, Script, ChannelStatsVideo, ChannelStats, including quota fields).
    • This keeps the API responses aligned with the DB functions (use_feature, get_feature_usage) and the dashboard components, so changes in the schema are enforced at compile time on both sides.

🚀 Deployment Notes

  • Run the new Supabase migration:
    • pnpm --filter @repo/supabase supabase:push (or your normal migration pipeline).
  • Ensure environment is linked correctly via supabase:link before running migrations.
  • No other special deployment steps beyond applying the migration and restarting the affected services.

📚 Documentation Updates

  • README.md updated (or will be updated to reference @repo/supabase scripts and shared validation types)
  • CONTRIBUTING.md updated (if applicable)
  • API documentation updated (if applicable)
  • Component documentation updated (if applicable)

(You can tick/untick depending on what you actually change.)

🔍 Review Notes

  • Please focus on:
    • The correctness of the use_feature and get_feature_usage logic (especially edge cases around day rollovers and multiple plans).
    • The shape of the shared billing and YouTube stats types, and whether they match current/expected API responses.
    • Any naming concerns for the new DB columns and TypeScript fields, since these will be reused widely on frontend and backend.

📊 Performance Impact

  • No performance impact
  • Performance improvement
  • Performance regression (explain below)

Details:

  • Moving quota checks and increments into a single SQL function reduces round-trips and eliminates race conditions, which is important under high usage.
  • Caching analytics in JSONB fields (top_videos, recent_videos, youtube_trained_videos) avoids recomputing heavy stats for every request.

🔒 Security Considerations

  • No security implications
  • Security improvement
  • Potential security concern (explain below)

Details:

  • Functions are defined as SECURITY DEFINER but operate only on the current user’s user_id row; they do not expose any new public data.
  • Quota enforcement in the DB helps prevent abuse of expensive operations (e.g. hitting external APIs) by enforcing limits centrally.

🎉 Additional Notes

  • This PR lays the foundation for future features that depend on plan-aware quotas and richer channel analytics, while keeping the schema strictly typed and shared between frontend and backend.
  • If we change plan limits or cooldown policies in the future, most changes will be data-only (updating plans rows) or localized to the two PL/pgSQL functions.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Feb 27, 2026

@GauravOP-03 is attempting to deploy a commit to the afrin127329's projects Team on Vercel.

A member of the Team first needs to authorize it.

@GauravOP-03 GauravOP-03 changed the title added supabase migration file for youtube stats, added validation sch… added supabase migration file for youtube stats, added validation schemas Feb 27, 2026
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