// Command sync-plans upserts public Free→Enterprise ladder meters into Postgres. // Usage (from apps/api): // // go run ./cmd/sync-plans -postgres "$DATABASE_URL" package main import ( "context" "flag" "fmt" "os" "strings" "time" "github.com/descrybe/descrybe-v2/apps/api/internal/billing" "github.com/jackc/pgx/v5/pgxpool" ) func main() { pg := flag.String("postgres", os.Getenv("DATABASE_URL"), "Postgres DATABASE_URL") flag.Parse() if strings.TrimSpace(*pg) == "" { fmt.Fprintln(os.Stderr, "DATABASE_URL or -postgres required") os.Exit(1) } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() pool, err := pgxpool.New(ctx, *pg) if err != nil { fmt.Fprintf(os.Stderr, "connect: %v\n", err) os.Exit(1) } defer pool.Close() svc := &billing.Service{Pool: pool} if err := svc.EnsureDefaultPlans(ctx); err != nil { fmt.Fprintf(os.Stderr, "EnsureDefaultPlans: %v\n", err) os.Exit(1) } rows, err := pool.Query(ctx, ` SELECT name, monthly_credits, COALESCE(max_products::text, 'unlimited') FROM plans WHERE lower(name) IN ('free','starter','plus','growth','business','scale','enterprise') ORDER BY CASE lower(name) WHEN 'free' THEN 0 WHEN 'starter' THEN 1 WHEN 'plus' THEN 2 WHEN 'growth' THEN 3 WHEN 'business' THEN 4 WHEN 'scale' THEN 5 WHEN 'enterprise' THEN 6 ELSE 9 END`) if err != nil { fmt.Fprintf(os.Stderr, "list: %v\n", err) os.Exit(1) } defer rows.Close() fmt.Println("Public plans synced:") for rows.Next() { var name, maxP string var credits int if err := rows.Scan(&name, &credits, &maxP); err != nil { fmt.Fprintf(os.Stderr, "scan: %v\n", err) os.Exit(1) } fmt.Printf(" %-12s credits=%-8d max_products=%s\n", name, credits, maxP) } if err := rows.Err(); err != nil { fmt.Fprintf(os.Stderr, "rows: %v\n", err) os.Exit(1) } }