diff --git a/lib/artists/__tests__/getFormattedArtist.test.ts b/lib/artists/__tests__/getFormattedArtist.test.ts new file mode 100644 index 00000000..5fd6d7a2 --- /dev/null +++ b/lib/artists/__tests__/getFormattedArtist.test.ts @@ -0,0 +1,38 @@ +import { describe, it, expect } from "vitest"; +import { getFormattedArtist } from "@/lib/artists/getFormattedArtist"; + +const row = { + artist_info: { + id: "acct-ebae", + name: "Apache", + account_info: [ + { + id: "info-33ad", + image: "img", + instruction: null, + knowledges: [], + label: "artist", + job_title: "CEO", + role_type: "manager", + company_name: "OneRPM", + organization: "org", + }, + ], + account_socials: [], + }, +} as never; + +describe("getFormattedArtist", () => { + it("returns id === account_id (never the account_info.id) so sub-resources resolve", () => { + const a = getFormattedArtist(row); + expect(a.account_id).toBe("acct-ebae"); + expect(a.id).toBe("acct-ebae"); // NOT "info-33ad" — /artists/{id}/socials keys on account_id + }); + + it("does not leak raw account_info fields (job_title/role_type/company_name/organization)", () => { + const a = getFormattedArtist(row) as Record; + for (const k of ["job_title", "role_type", "company_name", "organization"]) { + expect(a[k]).toBeUndefined(); + } + }); +}); diff --git a/lib/artists/__tests__/updateArtistHandler.test.ts b/lib/artists/__tests__/updateArtistHandler.test.ts index 2b717d82..c41d1b82 100644 --- a/lib/artists/__tests__/updateArtistHandler.test.ts +++ b/lib/artists/__tests__/updateArtistHandler.test.ts @@ -159,6 +159,7 @@ describe("updateArtistHandler", () => { }); expect(body.artist).toEqual({ account_id: artistId, + id: artistId, name: "Updated Artist", image: "https://example.com/new-image.jpg", instruction: "Stay on brand", diff --git a/lib/artists/getFormattedArtist.ts b/lib/artists/getFormattedArtist.ts index a4f75e72..be92126e 100644 --- a/lib/artists/getFormattedArtist.ts +++ b/lib/artists/getFormattedArtist.ts @@ -31,7 +31,10 @@ export interface ArtistQueryRow { // FormattedArtist composes fields from multiple tables + computed fields export interface FormattedArtist extends Pick { + /** The artist's account id. Equal to `id` — sub-resources (/socials|posts|fans) key on this. */ account_id: AccountRow["id"]; + /** Same value as `account_id`; kept so callers using `.id` for /artists/{id}/* also resolve. */ + id: AccountRow["id"]; name: AccountRow["name"]; account_socials: Array< Pick & { @@ -68,8 +71,14 @@ export function getFormattedArtist(row: ArtistQueryRow): FormattedArtist { return { name: artist.name, - ...info, + image: info.image, + instruction: info.instruction, + knowledges: info.knowledges, + label: info.label, account_id, + // `id` mirrors `account_id` — the list used to leak `account_info.id` here via + // `...info`, which the /artists/{id}/* sub-resources reject (they key on account_id). + id: account_id, account_socials, pinned: row.pinned || false, };