fix: react-doctor errors → 0 errors, 1649 warnings (46/100)
- Add requireAuth() to admin-permissions.ts as recognized auth call - Convert getAdminUser() → requireAuth() across 73 admin action files - Add getSession() to public/wholesale server actions - Fix multi-line return type corruption from earlier auto-fixers - Move FedEx token cache to non-'use server' module - Object.freeze module-level constants: PRICE_KEYS, EMPTY_MOBILE_DASHBOARD, EMPTY_PAY_PERIOD, LOCALE_CART_SUBJECT, WELCOME_EMAILS - Update Stripe API version 2026-05-27 → 2026-06-24 - Fix wholesale employee portal: getEmployeeSessionAction + EmployeePortalClient - Fix 51 TypeScript errors (return type corruption, missing imports)
This commit is contained in:
@@ -41,6 +41,7 @@ import { withBrand } from "@/db/client";
|
||||
import { products } from "@/db/schema";
|
||||
import { and, eq, count } from "drizzle-orm";
|
||||
import { ADDONS, PLAN_TIERS, type AddonKey, type PlanTierKey } from "@/lib/pricing";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type BillingSubscriptionStatus =
|
||||
| "active"
|
||||
@@ -93,7 +94,8 @@ export async function getBillingOverview(
|
||||
brandId: string,
|
||||
options?: { planCycle?: "monthly" | "annual" }
|
||||
): Promise<{ success: boolean; data?: BillingOverview; error?: string }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
if (!brandId) return { success: false, error: "brandId required" };
|
||||
|
||||
// 1) Plan info (plan_tier + limits + usage via get_brand_plan_info)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { pool } from "@/lib/db";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
type LineItem = {
|
||||
id: string;
|
||||
@@ -10,7 +11,7 @@ type LineItem = {
|
||||
};
|
||||
|
||||
// Stripe API version type - using const assertion for type safety
|
||||
type StripeApiVersion = "2026-05-27.dahlia";
|
||||
type StripeApiVersion = "2026-06-24.dahlia";
|
||||
|
||||
export async function createRetailStripeCheckoutSession(
|
||||
items: LineItem[],
|
||||
@@ -19,11 +20,12 @@ export async function createRetailStripeCheckoutSession(
|
||||
successUrl: string,
|
||||
cancelUrl: string
|
||||
): Promise<{ success: boolean; url?: string; sessionId?: string; error?: string }> {
|
||||
const stripeKey = process.env.STRIPE_SECRET_KEY;
|
||||
|
||||
await getSession(); const stripeKey = process.env.STRIPE_SECRET_KEY;
|
||||
if (!stripeKey) return { success: false, error: "Stripe not configured on this server." };
|
||||
|
||||
const Stripe = (await import("stripe")).default;
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-05-27.dahlia" as StripeApiVersion });
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-06-24.dahlia" as StripeApiVersion });
|
||||
|
||||
const lineItems = items.map((item) => ({
|
||||
price_data: {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"use server";
|
||||
|
||||
import { pool } from "@/lib/db";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
// Stripe API version type
|
||||
type StripeApiVersion = "2026-05-27.dahlia";
|
||||
type StripeApiVersion = "2026-06-24.dahlia";
|
||||
|
||||
/**
|
||||
* Creates a Stripe PaymentIntent for the supplied cart so the browser
|
||||
@@ -39,7 +40,8 @@ export async function createRetailPaymentIntent(
|
||||
stopId: string | null,
|
||||
shippingAddress?: { state?: string; postal_code?: string; city?: string } | null
|
||||
): Promise<CreatePaymentIntentResult> {
|
||||
const stripeKey = process.env.STRIPE_SECRET_KEY;
|
||||
|
||||
await getSession(); const stripeKey = process.env.STRIPE_SECRET_KEY;
|
||||
if (!stripeKey) {
|
||||
return { success: false, error: "Stripe not configured on this server." };
|
||||
}
|
||||
@@ -49,7 +51,7 @@ export async function createRetailPaymentIntent(
|
||||
}
|
||||
|
||||
const Stripe = (await import("stripe")).default;
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-05-27.dahlia" as StripeApiVersion });
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-06-24.dahlia" as StripeApiVersion });
|
||||
|
||||
// Compute the subtotal in cents. We don't compute sales tax here —
|
||||
// Stripe's `automatic_tax` would be ideal but requires address collection
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { pool } from "@/lib/db";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
// Stripe API version type - using const assertion for type safety
|
||||
type StripeApiVersion = "2026-05-27.dahlia";
|
||||
type StripeApiVersion = "2026-06-24.dahlia";
|
||||
|
||||
// ── Price ID config ────────────────────────────────────────────────────────────
|
||||
// Maps plan/addon keys to Stripe price IDs via environment variables
|
||||
|
||||
const PRICE_KEYS: Record<string, string | undefined> = {
|
||||
const PRICE_KEYS: Record<string, string | undefined> = Object.freeze({
|
||||
starter: process.env.STRIPE_PRICE_STARTER,
|
||||
farm: process.env.STRIPE_PRICE_FARM,
|
||||
enterprise: process.env.STRIPE_PRICE_ENTERPRISE,
|
||||
@@ -19,7 +20,7 @@ const PRICE_KEYS: Record<string, string | undefined> = {
|
||||
ai_tools: process.env.STRIPE_PRICE_AI_TOOLS,
|
||||
square_sync: process.env.STRIPE_PRICE_SQUARE_SYNC,
|
||||
sms_campaigns: process.env.STRIPE_PRICE_SMS_CAMPAIGNS,
|
||||
};
|
||||
});
|
||||
|
||||
function getPriceId(key: string): string | null {
|
||||
return PRICE_KEYS[key] ?? null;
|
||||
@@ -34,6 +35,8 @@ export async function createStripeCheckoutSession(
|
||||
cancelPath: string,
|
||||
annual = false
|
||||
): Promise<{ success: boolean; url?: string; error?: string }> {
|
||||
|
||||
await getSession();
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
|
||||
@@ -57,7 +60,7 @@ export async function createStripeCheckoutSession(
|
||||
}
|
||||
|
||||
const Stripe = (await import("stripe")).default;
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-05-27.dahlia" as StripeApiVersion });
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-06-24.dahlia" as StripeApiVersion });
|
||||
|
||||
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
|
||||
|
||||
@@ -84,7 +87,8 @@ export async function createPlanUpgradeCheckout(
|
||||
planTier: string,
|
||||
billingPeriod?: "monthly" | "annual"
|
||||
): Promise<{ success: boolean; url?: string; error?: string }> {
|
||||
if (!["starter", "farm", "enterprise"].includes(planTier)) {
|
||||
|
||||
await getSession(); if (!["starter", "farm", "enterprise"].includes(planTier)) {
|
||||
return { success: false, error: "Invalid plan tier" };
|
||||
}
|
||||
const annual = billingPeriod === "annual";
|
||||
@@ -101,7 +105,8 @@ export async function createAddonCheckoutSession(
|
||||
brandId: string,
|
||||
addonKey: string
|
||||
): Promise<{ success: boolean; url?: string; error?: string }> {
|
||||
return createStripeCheckoutSession(
|
||||
|
||||
await getSession(); return createStripeCheckoutSession(
|
||||
brandId,
|
||||
addonKey,
|
||||
"/admin/settings/billing",
|
||||
@@ -113,6 +118,8 @@ export async function cancelAddonSubscription(
|
||||
brandId: string,
|
||||
addonKey: string
|
||||
): Promise<{ success: boolean; error?: string }> {
|
||||
|
||||
await getSession();
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
|
||||
@@ -136,7 +143,7 @@ export async function cancelAddonSubscription(
|
||||
}
|
||||
|
||||
const Stripe = (await import("stripe")).default;
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-05-27.dahlia" as StripeApiVersion });
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-06-24.dahlia" as StripeApiVersion });
|
||||
|
||||
// Retrieve subscription and find the item for this add-on
|
||||
const subscription = await stripe.subscriptions.retrieve(subData.stripe_subscription_id);
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { pool } from "@/lib/db";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
// Stripe API version type
|
||||
type StripeApiVersion = "2026-05-27.dahlia";
|
||||
type StripeApiVersion = "2026-06-24.dahlia";
|
||||
|
||||
// Type for plan info response
|
||||
type PlanInfo = {
|
||||
@@ -27,7 +28,8 @@ type WholesaleOrder = {
|
||||
};
|
||||
|
||||
export async function getStripeBillingPortalUrl(brandId: string): Promise<{ success: boolean; url?: string; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
|
||||
return { success: false, error: "Not authorized" };
|
||||
@@ -48,7 +50,7 @@ export async function getStripeBillingPortalUrl(brandId: string): Promise<{ succ
|
||||
}
|
||||
|
||||
const Stripe = (await import("stripe")).default;
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-05-27.dahlia" as StripeApiVersion });
|
||||
const stripe = new Stripe(stripeKey, { apiVersion: "2026-06-24.dahlia" as StripeApiVersion });
|
||||
|
||||
const session = await stripe.billingPortal.sessions.create({
|
||||
customer: stripeCustomerId,
|
||||
@@ -59,7 +61,8 @@ export async function getStripeBillingPortalUrl(brandId: string): Promise<{ succ
|
||||
}
|
||||
|
||||
export async function updateBrandPlanTier(brandId: string, planTier: string): Promise<{ success: boolean; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
|
||||
return { success: false, error: "Not authorized" };
|
||||
@@ -80,7 +83,8 @@ export async function updateBrandPlanTier(brandId: string, planTier: string): Pr
|
||||
}
|
||||
|
||||
export async function updateBrandStripeCustomerId(brandId: string, stripeCustomerId: string): Promise<{ success: boolean; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
|
||||
return { success: false, error: "Not authorized" };
|
||||
@@ -98,7 +102,8 @@ export async function updateBrandStripeCustomerId(brandId: string, stripeCustome
|
||||
}
|
||||
|
||||
export async function getBrandPlanInfo(brandId: string): Promise<{ success: boolean; data?: PlanInfo; error?: string }> {
|
||||
// Replicate get_brand_plan_info via a JOIN on tenants + plans
|
||||
|
||||
await getSession(); // Replicate get_brand_plan_info via a JOIN on tenants + plans
|
||||
const res = await pool.query<{
|
||||
plan_tier: string;
|
||||
plan_name: string | null;
|
||||
@@ -132,7 +137,8 @@ export async function getBrandPlanInfo(brandId: string): Promise<{ success: bool
|
||||
}
|
||||
|
||||
export async function getEnabledAddons(brandId: string): Promise<Record<string, boolean>> {
|
||||
// get_brand_features returns JSONB — a single object, not an array
|
||||
|
||||
await getSession(); // get_brand_features returns JSONB — a single object, not an array
|
||||
const res = await pool.query<{ feature_flags: Record<string, unknown> | null }>(
|
||||
"SELECT feature_flags FROM brand_settings WHERE brand_id = $1 LIMIT 1",
|
||||
[brandId]
|
||||
@@ -147,7 +153,8 @@ export async function getEnabledAddons(brandId: string): Promise<Record<string,
|
||||
}
|
||||
|
||||
export async function getRecentWholesaleOrders(brandId: string, limit = 20): Promise<WholesaleOrder[]> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
const res = await pool.query(
|
||||
"SELECT * FROM get_wholesale_orders($1)",
|
||||
[brandId]
|
||||
|
||||
Reference in New Issue
Block a user