From c5d82524f8e0a6838d6f4031b7e06690a0e3dde7 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 17:17:17 -0500 Subject: [PATCH 1/3] SRP - selectAccountArtistIds --- .../selectAccountArtistIds.ts | 35 +++++++++++++++++++ lib/supabase/getArtistEmails.ts | 25 +++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 lib/supabase/account_artist_ids/selectAccountArtistIds.ts diff --git a/lib/supabase/account_artist_ids/selectAccountArtistIds.ts b/lib/supabase/account_artist_ids/selectAccountArtistIds.ts new file mode 100644 index 00000000..e75a66a1 --- /dev/null +++ b/lib/supabase/account_artist_ids/selectAccountArtistIds.ts @@ -0,0 +1,35 @@ +import serverClient from "@/lib/supabase/serverClient"; +import { Tables } from "@/types/database.types"; + +type AccountArtistId = Tables<"account_artist_ids">; + +type SelectAccountArtistIdsParams = { + artist_id?: string; + account_ids?: string[]; +}; + +/** + * Selects account_artist_ids with optional filters + */ +export async function selectAccountArtistIds( + params: SelectAccountArtistIdsParams +): Promise { + let query = serverClient.from("account_artist_ids").select("*"); + + // Add filters based on provided parameters + if (params.artist_id) { + query = query.eq("artist_id", params.artist_id); + } + + if (params.account_ids && params.account_ids.length > 0) { + query = query.in("account_id", params.account_ids); + } + + const { data, error } = await query; + + if (error) { + throw new Error(`Failed to fetch account_artist_ids: ${error.message}`); + } + + return data || []; +} diff --git a/lib/supabase/getArtistEmails.ts b/lib/supabase/getArtistEmails.ts index c36c6970..d5628927 100644 --- a/lib/supabase/getArtistEmails.ts +++ b/lib/supabase/getArtistEmails.ts @@ -1,4 +1,5 @@ import supabase from "./serverClient"; +import { selectAccountArtistIds } from "./account_artist_ids/selectAccountArtistIds"; interface ArtistEmailsResponse { emails: string[]; @@ -14,28 +15,20 @@ const getArtistEmails = async ( artistId: string ): Promise => { try { - const { data: accountArtists, error: accountArtistsError } = await supabase - .from("account_artist_ids") - .select("account_id") - .eq("artist_id", artistId); - if (accountArtistsError) { - console.error( - "[ERROR] Failed to get account_artist_ids:", - accountArtistsError - ); - return { - emails: [], - error: new Error("Failed to get artist accounts"), - }; - } - if (!accountArtists?.length) { + const accountArtists = await selectAccountArtistIds({ + artist_id: artistId, + }); + + if (!accountArtists || accountArtists.length === 0) { return { emails: [], error: new Error("No accounts found for artist"), }; } - const accountIds = accountArtists.map((aa) => aa.account_id); + const accountIds = accountArtists + .map((aa) => aa.account_id) + .filter((accountId): accountId is string => Boolean(accountId)); const { data: accountEmails, error: emailsError } = await supabase .from("account_emails") From 32a36be3ffab72eae0486fdc132a67a7d007017a Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 17:20:35 -0500 Subject: [PATCH 2/3] API - /api/artists/pro - call existing libs to get all artist_ids from all Pro accounts --- .../getArtistsProHandler.ts | 12 ++----- lib/enterprise/getEnterpriseArtists.ts | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 lib/enterprise/getEnterpriseArtists.ts diff --git a/controllers/ArtistsProController/getArtistsProHandler.ts b/controllers/ArtistsProController/getArtistsProHandler.ts index 00e64731..a753c1b3 100644 --- a/controllers/ArtistsProController/getArtistsProHandler.ts +++ b/controllers/ArtistsProController/getArtistsProHandler.ts @@ -1,22 +1,16 @@ import { Request, Response } from "express"; -import { getAllEnterpriseAccounts } from "@/lib/enterprise/getAllEnterpriseAccounts"; -import { getSubscriberAccountEmails } from "@/lib/stripe/getSubscriberAccountEmails"; +import { getEnterpriseArtists } from "@/lib/enterprise/getEnterpriseArtists"; /** * Handles GET requests for artists list - * Returns enterprise emails and account emails from active subscriptions + * Returns artists associated with pro accounts (enterprise and active subscriptions) */ export const getArtistsProHandler = async ( req: Request, res: Response ): Promise => { try { - const [allEnterpriseEmails, subscriptionAccountEmails] = await Promise.all([ - getAllEnterpriseAccounts(), - getSubscriberAccountEmails(), - ]); - - const artists = [...allEnterpriseEmails, ...subscriptionAccountEmails]; + const artists = await getEnterpriseArtists(); res.status(200).json({ status: "success", diff --git a/lib/enterprise/getEnterpriseArtists.ts b/lib/enterprise/getEnterpriseArtists.ts new file mode 100644 index 00000000..fa67265f --- /dev/null +++ b/lib/enterprise/getEnterpriseArtists.ts @@ -0,0 +1,36 @@ +import { getAllEnterpriseAccounts } from "@/lib/enterprise/getAllEnterpriseAccounts"; +import { getSubscriberAccountEmails } from "@/lib/stripe/getSubscriberAccountEmails"; +import { selectAccountArtistIds } from "@/lib/supabase/account_artist_ids/selectAccountArtistIds"; +import { Tables } from "@/types/database.types"; + +type AccountArtistId = Tables<"account_artist_ids">; + +/** + * Gets all artists associated with pro accounts (enterprise and active subscriptions) + * @returns Array of account_artist_ids records for pro accounts + */ +export const getEnterpriseArtists = async (): Promise => { + const [allEnterpriseEmails, subscriptionAccountEmails] = await Promise.all([ + getAllEnterpriseAccounts(), + getSubscriberAccountEmails(), + ]); + + // Extract unique account_ids from enterprise emails and subscription account emails + const allAccountEmails = [ + ...allEnterpriseEmails, + ...subscriptionAccountEmails, + ]; + const accountIds = new Set(); + allAccountEmails.forEach((email) => { + if (email.account_id) { + accountIds.add(email.account_id); + } + }); + + // Get all artists associated with pro accounts + if (accountIds.size === 0) { + return []; + } + + return await selectAccountArtistIds({ account_ids: Array.from(accountIds) }); +}; From deb4d7e9ade8ad89a6652cc2a482b1a65723bbda Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Fri, 14 Nov 2025 17:28:16 -0500 Subject: [PATCH 3/3] KISS - only array of artistIds instead of array of account_artist_id objects. --- lib/enterprise/getEnterpriseArtists.ts | 36 ++++++++++++++------------ 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/enterprise/getEnterpriseArtists.ts b/lib/enterprise/getEnterpriseArtists.ts index fa67265f..e4b9f4a2 100644 --- a/lib/enterprise/getEnterpriseArtists.ts +++ b/lib/enterprise/getEnterpriseArtists.ts @@ -1,36 +1,38 @@ import { getAllEnterpriseAccounts } from "@/lib/enterprise/getAllEnterpriseAccounts"; import { getSubscriberAccountEmails } from "@/lib/stripe/getSubscriberAccountEmails"; import { selectAccountArtistIds } from "@/lib/supabase/account_artist_ids/selectAccountArtistIds"; -import { Tables } from "@/types/database.types"; - -type AccountArtistId = Tables<"account_artist_ids">; /** * Gets all artists associated with pro accounts (enterprise and active subscriptions) - * @returns Array of account_artist_ids records for pro accounts + * @returns Array of unique artist_ids for pro accounts */ -export const getEnterpriseArtists = async (): Promise => { +export const getEnterpriseArtists = async (): Promise => { const [allEnterpriseEmails, subscriptionAccountEmails] = await Promise.all([ getAllEnterpriseAccounts(), getSubscriberAccountEmails(), ]); // Extract unique account_ids from enterprise emails and subscription account emails - const allAccountEmails = [ - ...allEnterpriseEmails, - ...subscriptionAccountEmails, - ]; - const accountIds = new Set(); - allAccountEmails.forEach((email) => { - if (email.account_id) { - accountIds.add(email.account_id); - } - }); + const accountIds = new Set( + [...allEnterpriseEmails, ...subscriptionAccountEmails] + .map((email) => email.account_id) + .filter((id): id is string => Boolean(id)) + ); - // Get all artists associated with pro accounts if (accountIds.size === 0) { return []; } - return await selectAccountArtistIds({ account_ids: Array.from(accountIds) }); + // Get artist_ids and deduplicate using Set + const accountArtistIds = await selectAccountArtistIds({ + account_ids: Array.from(accountIds), + }); + + return Array.from( + new Set( + accountArtistIds + .map((record) => record.artist_id) + .filter((id): id is string => Boolean(id)) + ) + ); };