From e6676608e07a5497b9f96499a81559a39289f548 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 15:48:31 -0500 Subject: [PATCH 1/5] getActiveSubscriptions - optional accountId --- lib/stripe/getActiveSubscriptions.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/stripe/getActiveSubscriptions.ts b/lib/stripe/getActiveSubscriptions.ts index 87ff4be7..38ed152f 100644 --- a/lib/stripe/getActiveSubscriptions.ts +++ b/lib/stripe/getActiveSubscriptions.ts @@ -1,7 +1,7 @@ import stripeClient from "./client"; import Stripe from "stripe"; -export const getActiveSubscriptions = async (accountId: string) => { +export const getActiveSubscriptions = async (accountId?: string) => { try { const subscriptions = await stripeClient.subscriptions.list({ limit: 100, @@ -10,11 +10,16 @@ export const getActiveSubscriptions = async (accountId: string) => { }, }); + // Return all active subscriptions if no accountId provided + if (!accountId) { + return subscriptions?.data || []; + } + + // Filter by accountId if provided const activeSubscriptions = subscriptions?.data?.filter( (subscription: Stripe.Subscription) => subscription.metadata?.accountId === accountId ); - return activeSubscriptions || []; } catch (error) { console.error("Error fetching subscriptions:", error); From 9d359869b1acfe514c41add9498802535d4b7e18 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 16:12:58 -0500 Subject: [PATCH 2/5] account_id => account_ids (plural) for batch lookup by accountId --- controllers/SubscriptionsController.ts | 2 +- lib/supabase/account_emails/getAccountEmails.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/controllers/SubscriptionsController.ts b/controllers/SubscriptionsController.ts index ef10268d..494bc7c7 100644 --- a/controllers/SubscriptionsController.ts +++ b/controllers/SubscriptionsController.ts @@ -25,7 +25,7 @@ export const getSubscriptionsHandler = async ( } // Get account emails to check if any belong to enterprise domain - const accountEmails = await getAccountEmails({ account_id: accountId }); + const accountEmails = await getAccountEmails({ account_ids: [accountId] }); if (!accountEmails || accountEmails.length === 0) { res.status(404).json({ diff --git a/lib/supabase/account_emails/getAccountEmails.ts b/lib/supabase/account_emails/getAccountEmails.ts index a76a3933..626c3d70 100644 --- a/lib/supabase/account_emails/getAccountEmails.ts +++ b/lib/supabase/account_emails/getAccountEmails.ts @@ -4,7 +4,7 @@ import { Tables } from "../../../types/database.types"; type AccountEmail = Tables<"account_emails">; type GetAccountEmailsParams = { - account_id?: string; + account_ids?: string[]; queryEmail?: string; }; @@ -17,8 +17,8 @@ export const getAccountEmails = async ( let query = serverClient.from("account_emails").select("*"); // Add filters based on provided parameters - if (params.account_id) { - query = query.eq("account_id", params.account_id); + if (params.account_ids && params.account_ids.length > 0) { + query = query.in("account_id", params.account_ids); } if (params.queryEmail) { From 34b409146b2e6b81928b820cdd0c2644301c1468 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 16:16:13 -0500 Subject: [PATCH 3/5] API - /api/artists/pro - lib for getting all account_id from Stripe subscriptions associated with Pro accounts --- .../getArtistsProHandler.ts | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/controllers/ArtistsProController/getArtistsProHandler.ts b/controllers/ArtistsProController/getArtistsProHandler.ts index e5a28c83..a8fd477e 100644 --- a/controllers/ArtistsProController/getArtistsProHandler.ts +++ b/controllers/ArtistsProController/getArtistsProHandler.ts @@ -1,9 +1,12 @@ import { Request, Response } from "express"; import { getAllEnterpriseAccounts } from "@/lib/enterprise/getAllEnterpriseAccounts"; +import { getActiveSubscriptions } from "@/lib/stripe/getActiveSubscriptions"; +import { getAccountEmails } from "@/lib/supabase/account_emails/getAccountEmails"; +import Stripe from "stripe"; /** * Handles GET requests for artists list - * Returns enterprise emails + * Returns enterprise emails and account emails from active subscriptions */ export const getArtistsProHandler = async ( req: Request, @@ -11,10 +14,28 @@ export const getArtistsProHandler = async ( ): Promise => { try { const allEnterpriseEmails = await getAllEnterpriseAccounts(); + const activeSubscriptions = await getActiveSubscriptions(); + + // Extract accountIds from subscription metadata + const accountIds = activeSubscriptions + .map( + (subscription: Stripe.Subscription) => subscription.metadata?.accountId + ) + .filter((accountId: string | undefined): accountId is string => + Boolean(accountId) + ); + + // Get account emails for subscriptions with accountIds + const subscriptionAccountEmails = + accountIds.length > 0 + ? await getAccountEmails({ account_ids: accountIds }) + : []; + + const artists = [...allEnterpriseEmails, ...subscriptionAccountEmails]; res.status(200).json({ status: "success", - artists: allEnterpriseEmails, + artists, }); } catch (error) { console.error("[ERROR] Error in getArtistsProHandler:", error); From 38c1dccf457104c8ea27e9bbccc36c24724be11b Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 16:18:25 -0500 Subject: [PATCH 4/5] SRP - getSubscriberAccountEmails --- .../getArtistsProHandler.ts | 25 +++------------ lib/stripe/getSubscriberAccountEmails.ts | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 lib/stripe/getSubscriberAccountEmails.ts diff --git a/controllers/ArtistsProController/getArtistsProHandler.ts b/controllers/ArtistsProController/getArtistsProHandler.ts index a8fd477e..00e64731 100644 --- a/controllers/ArtistsProController/getArtistsProHandler.ts +++ b/controllers/ArtistsProController/getArtistsProHandler.ts @@ -1,8 +1,6 @@ import { Request, Response } from "express"; import { getAllEnterpriseAccounts } from "@/lib/enterprise/getAllEnterpriseAccounts"; -import { getActiveSubscriptions } from "@/lib/stripe/getActiveSubscriptions"; -import { getAccountEmails } from "@/lib/supabase/account_emails/getAccountEmails"; -import Stripe from "stripe"; +import { getSubscriberAccountEmails } from "@/lib/stripe/getSubscriberAccountEmails"; /** * Handles GET requests for artists list @@ -13,23 +11,10 @@ export const getArtistsProHandler = async ( res: Response ): Promise => { try { - const allEnterpriseEmails = await getAllEnterpriseAccounts(); - const activeSubscriptions = await getActiveSubscriptions(); - - // Extract accountIds from subscription metadata - const accountIds = activeSubscriptions - .map( - (subscription: Stripe.Subscription) => subscription.metadata?.accountId - ) - .filter((accountId: string | undefined): accountId is string => - Boolean(accountId) - ); - - // Get account emails for subscriptions with accountIds - const subscriptionAccountEmails = - accountIds.length > 0 - ? await getAccountEmails({ account_ids: accountIds }) - : []; + const [allEnterpriseEmails, subscriptionAccountEmails] = await Promise.all([ + getAllEnterpriseAccounts(), + getSubscriberAccountEmails(), + ]); const artists = [...allEnterpriseEmails, ...subscriptionAccountEmails]; diff --git a/lib/stripe/getSubscriberAccountEmails.ts b/lib/stripe/getSubscriberAccountEmails.ts new file mode 100644 index 00000000..901fea16 --- /dev/null +++ b/lib/stripe/getSubscriberAccountEmails.ts @@ -0,0 +1,31 @@ +import { getActiveSubscriptions } from "./getActiveSubscriptions"; +import { getAccountEmails } from "@/lib/supabase/account_emails/getAccountEmails"; +import Stripe from "stripe"; +import { Tables } from "@/types/database.types"; + +type AccountEmail = Tables<"account_emails">; + +/** + * Gets account emails for all active subscriptions + * Extracts accountIds from subscription metadata and fetches corresponding account emails + * @returns Array of account emails from active subscriptions + */ +export const getSubscriberAccountEmails = async (): Promise => { + const activeSubscriptions = await getActiveSubscriptions(); + + // Extract accountIds from subscription metadata + const accountIds = activeSubscriptions + .map( + (subscription: Stripe.Subscription) => subscription.metadata?.accountId + ) + .filter((accountId: string | undefined): accountId is string => + Boolean(accountId) + ); + + // Get account emails for subscriptions with accountIds + if (accountIds.length === 0) { + return []; + } + + return await getAccountEmails({ account_ids: accountIds }); +}; From b300b8ccb068ca4df5a3202d35ccdae357c6e949 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 16:19:45 -0500 Subject: [PATCH 5/5] parallelize calls in getAllEnterpriseAccounts --- lib/enterprise/getAllEnterpriseAccounts.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/enterprise/getAllEnterpriseAccounts.ts b/lib/enterprise/getAllEnterpriseAccounts.ts index 0fd40b9d..a34658a1 100644 --- a/lib/enterprise/getAllEnterpriseAccounts.ts +++ b/lib/enterprise/getAllEnterpriseAccounts.ts @@ -9,13 +9,13 @@ type AccountEmail = Tables<"account_emails">; * @returns Array of account emails from enterprise domains */ export const getAllEnterpriseAccounts = async (): Promise => { - const allEnterpriseEmails: AccountEmail[] = []; + // Query for each enterprise domain using queryEmail parameter in parallel + const emailPromises = Array.from(ENTERPRISE_DOMAINS).map((domain) => + getAccountEmails({ queryEmail: `@${domain}` }) + ); - // Query for each enterprise domain using queryEmail parameter - for (const domain of ENTERPRISE_DOMAINS) { - const emails = await getAccountEmails({ queryEmail: `@${domain}` }); - allEnterpriseEmails.push(...emails); - } + const emailArrays = await Promise.all(emailPromises); - return allEnterpriseEmails; + // Flatten the array of arrays into a single array + return emailArrays.flat(); };