Skip to content

Conversation

@sweetmantech
Copy link
Contributor

@sweetmantech sweetmantech commented Jan 15, 2026

Summary

  • Refactored artist creation from GET /api/artist/create with query params to POST /api/artist with JSON body
  • Returns 201 status on successful creation (proper RESTful behavior)
  • Created validateCreateArtistBody.ts for JSON body validation
  • Created createArtistPostHandler.ts for POST requests
  • Deleted old GET endpoint files (createArtistHandler.ts, validateCreateArtistQuery.ts)

Test plan

  • All 478 unit tests pass in recoup-api
  • All 9 unit tests pass in Recoup-Chat
  • Recoup-Chat build succeeds
  • Red-green-refactor followed: 18 failing tests written first, then implementation made them pass

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added artist creation API endpoint with CORS support
    • Introduced artist creation tool for MCP integration
    • Added ability to copy existing conversations to newly created artist accounts
    • Implemented optional organization linkage during artist creation
  • Tests

    • Added comprehensive test coverage for artist creation workflows, validation, and error handling
    • Added tests for conversation copying functionality

✏️ Tip: You can customize this high-level summary in your review settings.

sweetmantech and others added 3 commits January 15, 2026 08:37
Migrate the create_new_artist MCP tool from Recoup-Chat to recoup-api.
This tool creates a new artist account and optionally copies a conversation
to the new artist.

Components added:
- insertAccountArtistId: Associate artist with owner account
- selectAccountWithSocials: Fetch account with socials and info
- createArtistInDb: Orchestrate artist creation (account, info, owner link, org link)
- copyRoom: Copy conversation to new artist
- registerCreateNewArtistTool: MCP tool registration with zod schema
- artists/index.ts: Artist tools index

All 22 new unit tests pass (460 total).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…coup-api

Add new GET endpoint for creating artists with query parameters:
- validateCreateArtistQuery.ts: Zod validation for name + account_id
- createArtistHandler.ts: handler with CORS, validation, and createArtistInDb
- app/api/artist/create/route.ts: GET endpoint with OPTIONS for CORS

Reuses createArtistInDb from MYC-3923 migration.

Tests: 13 new unit tests (473 total)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactored artist creation endpoint from GET with query params to POST with
JSON body for REST compliance. POST to collection creates resource is more
RESTful than using GET with side effects.

Changes:
- Created validateCreateArtistBody.ts for JSON body validation
- Created createArtistPostHandler.ts for POST requests
- Created app/api/artist/route.ts with POST handler
- Deleted old GET endpoint files (createArtistHandler.ts, validateCreateArtistQuery.ts)
- Returns 201 status on successful creation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Jan 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
recoup-api Error Error Jan 15, 2026 2:06pm

@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

This PR introduces a complete artist creation feature spanning API routes, database operations, input validation, room cloning, and MCP tool integration. It includes an API endpoint, validation layer, multi-step database transaction orchestration, utility functions for room copying and account linking, and comprehensive test coverage across all modules.

Changes

Cohort / File(s) Summary
API Route Setup
app/api/artist/route.ts
New Next.js API endpoint with OPTIONS (CORS preflight) and POST (delegates to handler) handlers; exports configuration for dynamic routing, cache control, and revalidation.
Artist Creation Core Logic
lib/artists/createArtistPostHandler.ts, lib/artists/createArtistInDb.ts, lib/artists/validateCreateArtistBody.ts
Request handler that parses/validates JSON input and calls DB creation; validateCreateArtistBody uses Zod schema for input validation; createArtistInDb orchestrates multi-step DB flow (account insertion, account info, fetch full data, link artist to owner, optional organization linkage) with error handling at each step.
Supabase Database Operations
lib/supabase/accounts/selectAccountWithSocials.ts, lib/supabase/account_artist_ids/insertAccountArtistId.ts
New utilities for querying accounts with related socials/info and inserting account-artist relationships; typed return values with error handling for missing data.
Room Management
lib/rooms/copyRoom.ts
Clones a source room to a new artist, generating new UUID and updating artist_id; defaults topic to "New conversation" if source is null.
MCP Tool Integration
lib/mcp/tools/artists/registerCreateNewArtistTool.ts, lib/mcp/tools/artists/index.ts, lib/mcp/tools/index.ts
New artist tool with Zod-validated schema (name, account_id, optional active_conversation_id, organization_id); registerCreateNewArtistTool handles creation and optional room copying; registerAllArtistTools aggregator registered in main registerAllTools.
Comprehensive Test Suites
lib/artists/__tests__/createArtistPostHandler.test.ts, lib/artists/__tests__/createArtistInDb.test.ts, lib/artists/__tests__/validateCreateArtistBody.test.ts, lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts, lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts, lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts, lib/rooms/__tests__/copyRoom.test.ts
Tests covering success and failure paths, validation errors, CORS headers, DB operation sequences, optional field handling, and error propagation.

Sequence Diagram

sequenceDiagram
    participant Client
    participant API as POST /api/artist
    participant Validate as validateCreateArtistBody
    participant Handler as createArtistPostHandler
    participant CreateDB as createArtistInDb
    participant Supabase as Supabase DB
    participant RoomCopy as copyRoom
    participant MCP as MCP Tool

    Client->>API: POST with {name, account_id}
    API->>Handler: delegate to createArtistPostHandler
    Handler->>Validate: validateCreateArtistBody(body)
    alt Validation fails
        Validate-->>Handler: NextResponse error (400)
        Handler-->>Client: error response + CORS headers
    else Validation succeeds
        Validate-->>Handler: validated data
        Handler->>CreateDB: createArtistInDb(name, account_id, org_id?)
        CreateDB->>Supabase: insertAccount(name)
        Supabase-->>CreateDB: account
        CreateDB->>Supabase: insertAccountInfo(account.id, fields)
        Supabase-->>CreateDB: account_info
        CreateDB->>Supabase: selectAccountWithSocials(account.id)
        Supabase-->>CreateDB: full account with socials
        CreateDB->>Supabase: insertAccountArtistId(account_id, artist_id)
        Supabase-->>CreateDB: artist link confirmed
        opt if organization_id provided
            CreateDB->>Supabase: addArtistToOrganization
            Supabase-->>CreateDB: org link
        end
        CreateDB-->>Handler: CreateArtistResult
        Handler-->>Client: 201 with artist data + CORS headers
    end
    opt MCP integration
        MCP->>CreateDB: registerCreateNewArtistTool calls createArtistInDb
        CreateDB->>Supabase: (same flow)
        opt if active_conversation_id
            CreateDB->>RoomCopy: copyRoom(source_id, artist_id)
            RoomCopy->>Supabase: insert new room
            Supabase-->>RoomCopy: new room id
            RoomCopy-->>CreateDB: newRoomId
        end
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related PRs

Poem

🐰 A brand new artist springs to life,
With room to think, and tools without strife,
Validated soundly, from head to toe,
Through Supabase gardens our data will flow! 🌱✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: refactor GET /api/artist/create to POST /api/artist' clearly and specifically summarizes the main change: migrating an artist creation endpoint from a GET request to a POST request with a new URL structure.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@lib/artists/createArtistInDb.ts`:
- Around line 44-49: The code calls insertAccount and immediately uses
account.id without checking for a null/undefined return; update createArtistInDb
(around the insertAccount call) to validate the account result and return null
(or handle error) if insertAccount returned null/undefined before calling
insertAccountInfo, mirroring the existing accountInfo null-check pattern so you
don't attempt to access account.id when account is falsy.
🧹 Nitpick comments (9)
lib/rooms/copyRoom.ts (1)

37-39: Consider logging errors before returning null.

The catch block silently swallows all errors, which can make debugging difficult in production. Adding error logging would improve observability without changing the return behavior.

🔧 Optional: Add error logging
-  } catch {
+  } catch (error) {
+    console.error("Failed to copy room:", error);
     return null;
   }
lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts (1)

24-40: Good test coverage for the success path.

The test correctly verifies the table name and insert payload. Consider adding assertions for the full chain if you want complete coverage:

🔧 Optional: Assert full method chain
     expect(mockFrom).toHaveBeenCalledWith("account_artist_ids");
     expect(mockInsert).toHaveBeenCalledWith({
       account_id: "account-456",
       artist_id: "artist-789",
     });
+    expect(mockSelect).toHaveBeenCalled();
+    expect(mockSingle).toHaveBeenCalled();
     expect(result).toEqual(mockData);
lib/supabase/accounts/selectAccountWithSocials.ts (1)

1-32: Consider renaming to follow join query convention.

The implementation is correct and handles errors appropriately. However, per coding guidelines, complex Supabase queries with joins should be named get[Descriptive].ts rather than select[TableName].ts. Since this query includes joins for account_socials and account_info, consider renaming to getAccountWithSocials.ts.

That said, the current name is descriptive and the logic is sound—this is a minor naming convention suggestion.

lib/artists/validateCreateArtistBody.ts (1)

22-43: Consider a discriminated return type for cleaner consumption.

The union return type NextResponse | CreateArtistBody works but requires instanceof checks at call sites. A result pattern like { success: true, data: CreateArtistBody } | { success: false, response: NextResponse } would make the code more type-safe and explicit.

This is a minor ergonomics suggestion—the current approach is functional.

lib/artists/createArtistInDb.ts (1)

85-87: Silent error swallowing hampers debugging.

The catch block discards all error information. Consider logging the error for observability, even if the function still returns null.

♻️ Proposed fix
-  } catch (error) {
+  } catch (error) {
+    console.error("createArtistInDb failed:", error);
     return null;
   }
lib/artists/__tests__/createArtistInDb.test.ts (1)

83-94: Missing test for addArtistToOrganization failure.

The test verifies the happy path when organizationId is provided, but doesn't test what happens when addArtistToOrganization throws. Add a test case to verify the function returns null when organization linkage fails.

🧪 Proposed test case
it("returns null when adding artist to organization fails", async () => {
  mockInsertAccount.mockResolvedValue(mockAccount);
  mockInsertAccountInfo.mockResolvedValue(mockAccountInfo);
  mockSelectAccountWithSocials.mockResolvedValue(mockFullAccount);
  mockInsertAccountArtistId.mockResolvedValue({ id: "rel-123" });
  mockAddArtistToOrganization.mockRejectedValue(new Error("Organization link failed"));

  const result = await createArtistInDb("Test Artist", "owner-456", "org-789");

  expect(result).toBeNull();
});
lib/artists/createArtistPostHandler.ts (1)

60-68: Consider using 500 for unexpected server errors.

The catch block returns 400 for all exceptions, including potential database connection failures or internal server errors. A 400 status implies a client error, but exceptions from createArtistInDb could be server-side issues that warrant a 500 response.

Suggested approach
   } catch (error) {
     const message = error instanceof Error ? error.message : "failed";
     return NextResponse.json(
       { message },
       {
-        status: 400,
+        status: 500,
         headers: getCorsHeaders(),
       },
     );
   }
lib/artists/__tests__/createArtistPostHandler.test.ts (1)

146-158: Consider adding CORS header assertion for invalid JSON response.

This test verifies the 400 status and error message for invalid JSON, but doesn't verify that CORS headers are included. For consistency with the other error response tests (lines 179-196), consider adding an assertion for CORS headers here as well.

Suggested addition
     expect(response.status).toBe(400);
     expect(data.message).toBe("Invalid JSON body");
+    expect(response.headers.get("Access-Control-Allow-Origin")).toBe("*");
   });
lib/mcp/tools/artists/registerCreateNewArtistTool.ts (1)

32-42: Consider aligning CreateNewArtistResult with actual return values.

The interface defines artist and error as optional, but the success path (lines 83-92) always includes artist, and only the error path would include error. Consider using a discriminated union for stricter typing if desired, though the current approach is functional.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 01c4dca and 343baf8.

📒 Files selected for processing (17)
  • app/api/artist/route.ts
  • lib/artists/__tests__/createArtistInDb.test.ts
  • lib/artists/__tests__/createArtistPostHandler.test.ts
  • lib/artists/__tests__/validateCreateArtistBody.test.ts
  • lib/artists/createArtistInDb.ts
  • lib/artists/createArtistPostHandler.ts
  • lib/artists/validateCreateArtistBody.ts
  • lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts
  • lib/mcp/tools/artists/index.ts
  • lib/mcp/tools/artists/registerCreateNewArtistTool.ts
  • lib/mcp/tools/index.ts
  • lib/rooms/__tests__/copyRoom.test.ts
  • lib/rooms/copyRoom.ts
  • lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts
  • lib/supabase/account_artist_ids/insertAccountArtistId.ts
  • lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts
  • lib/supabase/accounts/selectAccountWithSocials.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Apply Single Responsibility Principle (SRP) - one exported function per file
Apply DRY principle (Don't Repeat Yourself) - extract shared logic into reusable utilities

Files:

  • lib/artists/__tests__/createArtistPostHandler.test.ts
  • lib/mcp/tools/index.ts
  • lib/artists/createArtistPostHandler.ts
  • lib/rooms/copyRoom.ts
  • lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts
  • lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts
  • lib/mcp/tools/artists/index.ts
  • lib/mcp/tools/artists/registerCreateNewArtistTool.ts
  • lib/artists/validateCreateArtistBody.ts
  • app/api/artist/route.ts
  • lib/artists/createArtistInDb.ts
  • lib/artists/__tests__/createArtistInDb.test.ts
  • lib/supabase/accounts/selectAccountWithSocials.ts
  • lib/supabase/account_artist_ids/insertAccountArtistId.ts
  • lib/artists/__tests__/validateCreateArtistBody.test.ts
  • lib/rooms/__tests__/copyRoom.test.ts
  • lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts
!(lib/supabase)/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

NEVER import @/lib/supabase/serverClient outside of lib/supabase/ directory

Files:

  • lib/artists/__tests__/createArtistPostHandler.test.ts
  • lib/mcp/tools/index.ts
  • lib/artists/createArtistPostHandler.ts
  • lib/rooms/copyRoom.ts
  • lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts
  • lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts
  • lib/mcp/tools/artists/index.ts
  • lib/mcp/tools/artists/registerCreateNewArtistTool.ts
  • lib/artists/validateCreateArtistBody.ts
  • app/api/artist/route.ts
  • lib/artists/createArtistInDb.ts
  • lib/artists/__tests__/createArtistInDb.test.ts
  • lib/supabase/accounts/selectAccountWithSocials.ts
  • lib/supabase/account_artist_ids/insertAccountArtistId.ts
  • lib/artists/__tests__/validateCreateArtistBody.test.ts
  • lib/rooms/__tests__/copyRoom.test.ts
  • lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts
lib/supabase/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

lib/supabase/**/*.{ts,tsx}: All Supabase database calls must be in lib/supabase/[table_name]/[function].ts
Supabase select functions should be named select[TableName].ts
Supabase insert functions should be named insert[TableName].ts
Supabase update functions should be named update[TableName].ts
Supabase delete functions should be named delete[TableName].ts
Complex Supabase queries with joins should be named get[Descriptive].ts

Files:

  • lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts
  • lib/supabase/accounts/selectAccountWithSocials.ts
  • lib/supabase/account_artist_ids/insertAccountArtistId.ts
  • lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts
app/api/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

app/api/**/*.{ts,tsx}: All API routes should have JSDoc comments
All API endpoints should use a validate function for input parsing with Zod for schema validation

Files:

  • app/api/artist/route.ts
🧠 Learnings (5)
📚 Learning: 2026-01-14T22:12:03.883Z
Learnt from: CR
Repo: Recoupable-com/Recoup-API PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T22:12:03.883Z
Learning: Applies to lib/supabase/**/*.{ts,tsx} : Supabase select functions should be named `select[TableName].ts`

Applied to files:

  • lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts
  • lib/supabase/accounts/selectAccountWithSocials.ts
📚 Learning: 2026-01-14T22:12:03.883Z
Learnt from: CR
Repo: Recoupable-com/Recoup-API PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T22:12:03.883Z
Learning: Applies to lib/@(auth|chats|emails|ai|x402|trigger)/**/*.{ts,tsx} : When needing database access in domain folders (lib/auth/, lib/chats/, etc.), first check if a function exists in `lib/supabase/[table_name]/`, create it if not, then import and use it

Applied to files:

  • lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts
  • lib/supabase/accounts/selectAccountWithSocials.ts
  • lib/supabase/account_artist_ids/insertAccountArtistId.ts
📚 Learning: 2026-01-14T22:12:03.883Z
Learnt from: CR
Repo: Recoupable-com/Recoup-API PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T22:12:03.883Z
Learning: Applies to app/api/**/*.{ts,tsx} : All API endpoints should use a validate function for input parsing with Zod for schema validation

Applied to files:

  • lib/artists/validateCreateArtistBody.ts
📚 Learning: 2026-01-14T22:12:03.883Z
Learnt from: CR
Repo: Recoupable-com/Recoup-API PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T22:12:03.883Z
Learning: Applies to lib/validation/**/*.{ts,tsx} : Create `validate<EndpointName>Body.ts` files for POST/PUT request body validation

Applied to files:

  • lib/artists/validateCreateArtistBody.ts
  • lib/artists/__tests__/validateCreateArtistBody.test.ts
📚 Learning: 2026-01-14T22:12:03.883Z
Learnt from: CR
Repo: Recoupable-com/Recoup-API PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T22:12:03.883Z
Learning: Applies to lib/supabase/**/*.{ts,tsx} : Supabase insert functions should be named `insert[TableName].ts`

Applied to files:

  • lib/supabase/account_artist_ids/insertAccountArtistId.ts
  • lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts
🧬 Code graph analysis (14)
lib/artists/__tests__/createArtistPostHandler.test.ts (2)
lib/artists/createArtistPostHandler.ts (1)
  • createArtistPostHandler (16-70)
lib/segments/createSegmentResponses.ts (1)
  • errorResponse (23-29)
lib/mcp/tools/index.ts (1)
lib/mcp/tools/artists/index.ts (1)
  • registerAllArtistTools (9-11)
lib/rooms/copyRoom.ts (3)
lib/supabase/rooms/selectRoom.ts (1)
  • selectRoom (12-22)
lib/uuid/generateUUID.ts (1)
  • generateUUID (8-20)
lib/supabase/rooms/insertRoom.ts (1)
  • insertRoom (8-14)
lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts (1)
lib/mcp/tools/artists/registerCreateNewArtistTool.ts (1)
  • registerCreateNewArtistTool (50-102)
lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts (1)
lib/supabase/accounts/selectAccountWithSocials.ts (1)
  • selectAccountWithSocials (18-32)
lib/mcp/tools/artists/index.ts (1)
lib/mcp/tools/artists/registerCreateNewArtistTool.ts (1)
  • registerCreateNewArtistTool (50-102)
lib/artists/validateCreateArtistBody.ts (1)
lib/networking/getCorsHeaders.ts (1)
  • getCorsHeaders (6-12)
app/api/artist/route.ts (2)
lib/networking/getCorsHeaders.ts (1)
  • getCorsHeaders (6-12)
lib/artists/createArtistPostHandler.ts (1)
  • createArtistPostHandler (16-70)
lib/artists/__tests__/createArtistInDb.test.ts (1)
lib/artists/createArtistInDb.ts (1)
  • createArtistInDb (38-88)
lib/supabase/accounts/selectAccountWithSocials.ts (1)
types/database.types.ts (1)
  • Tables (3819-3844)
lib/supabase/account_artist_ids/insertAccountArtistId.ts (1)
types/database.types.ts (1)
  • Tables (3819-3844)
lib/artists/__tests__/validateCreateArtistBody.test.ts (1)
lib/artists/validateCreateArtistBody.ts (2)
  • createArtistBodySchema (5-12)
  • validateCreateArtistBody (22-43)
lib/rooms/__tests__/copyRoom.test.ts (1)
lib/rooms/copyRoom.ts (1)
  • copyRoom (13-40)
lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts (1)
lib/supabase/account_artist_ids/insertAccountArtistId.ts (1)
  • insertAccountArtistId (15-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Vercel Agent Review
🔇 Additional comments (24)
lib/rooms/__tests__/copyRoom.test.ts (1)

1-85: LGTM! Comprehensive test coverage for copyRoom.

The test suite covers the key scenarios: successful copy, default topic handling, non-existent source room, and insertion failure. The mock setup is clean and correctly hoisted before the import.

lib/rooms/copyRoom.ts (1)

1-40: Clean implementation following project conventions.

The function correctly:

  • Imports Supabase helpers from the appropriate lib/supabase/rooms/ directory
  • Follows SRP with a single exported function
  • Provides clear JSDoc documentation
  • Handles the null source room case explicitly
lib/artists/__tests__/validateCreateArtistBody.test.ts (1)

1-109: Well-structured validation tests with good coverage.

The test suite thoroughly covers both the Zod schema and the wrapper function, including:

  • Valid input acceptance
  • Missing required fields (name, account_id)
  • Invalid UUID format
  • Empty string validation
  • Error response structure and CORS headers

Based on learnings, the file naming follows the validate<EndpointName>Body.ts convention.

lib/supabase/account_artist_ids/insertAccountArtistId.ts (1)

1-37: LGTM! Follows Supabase helper conventions.

The implementation correctly:

  • Is located in lib/supabase/account_artist_ids/ per coding guidelines
  • Follows the insert[TableName].ts naming convention (based on learnings)
  • Imports serverClient from within the lib/supabase/ directory (allowed)
  • Provides descriptive error messages for debugging
  • Uses .select().single() to return the inserted record
lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.ts (1)

42-59: Error case tests are well-structured.

Both error scenarios (Supabase error and missing data) are properly tested with appropriate error message assertions matching the implementation.

lib/supabase/accounts/__tests__/selectAccountWithSocials.test.ts (1)

1-62: LGTM!

The test suite provides good coverage for the three key scenarios: successful retrieval, not found, and query failure. The mock chain correctly mirrors the Supabase query builder pattern, and assertions properly verify both the method calls and return values.

lib/artists/validateCreateArtistBody.ts (1)

5-12: LGTM - Well-structured Zod schema.

The schema correctly validates the required fields with appropriate error messages and UUID format checking for account_id.

lib/artists/__tests__/createArtistInDb.test.ts (1)

31-62: LGTM - Well-structured test fixtures and setup.

The mock data structures accurately represent the expected shapes, and the beforeEach cleanup ensures test isolation. The test coverage for the various failure paths is thorough.

lib/artists/createArtistInDb.ts (1)

55-61: Check return value of addArtistToOrganization for failure.

insertAccountArtistId throws on failure, so errors propagate correctly. However, addArtistToOrganization returns null on failure (line 57), and the current code ignores the return value. If the organization link fails, the function silently succeeds with incomplete data.

lib/artists/createArtistPostHandler.ts (2)

1-35: LGTM!

The imports, JSDoc documentation, JSON parsing with error handling, and validation flow are well-structured. The handler correctly returns early with the validation response when validation fails.


37-59: LGTM!

The success path correctly returns 201 for resource creation, and the null check appropriately returns 500 for failed DB operations. CORS headers are consistently applied.

lib/artists/__tests__/createArtistPostHandler.test.ts (3)

1-16: LGTM!

The mock setup correctly uses vi.mock hoisting with factory functions that delegate to mock functions, allowing per-test customization while maintaining proper module isolation.


43-63: LGTM!

Good test coverage verifying the happy path: 201 status, artist data in response, and correct arguments passed to createArtistInDb.


84-144: LGTM!

Good coverage of error scenarios: validation failures, null DB results, and thrown exceptions. The assertions correctly verify status codes and response messages.

app/api/artist/route.ts (1)

1-35: LGTM!

Well-structured API route with proper JSDoc documentation on both handlers. The POST handler correctly delegates to the dedicated handler function, maintaining separation of concerns. Route configuration appropriately disables caching for this mutating endpoint. As per coding guidelines, validation is handled via Zod in the delegated handler.

lib/mcp/tools/artists/registerCreateNewArtistTool.ts (2)

8-28: LGTM!

Well-defined Zod schema with appropriate descriptions for MCP tool integration. The schema correctly marks active_conversation_id and organization_id as optional, with organization_id also allowing null to distinguish between omitted and explicitly unset values.


50-101: LGTM!

The tool registration follows a clean pattern: validate input via Zod schema, create artist in DB, optionally copy room, and return structured results. Error handling appropriately distinguishes between null returns (creation failed) and thrown exceptions. The JSDoc adequately documents the tool's purpose.

lib/mcp/tools/artists/index.ts (1)

1-11: LGTM!

Clean aggregator module following the established pattern for tool registration. The JSDoc documentation is clear, and the structure allows easy addition of future artist-related tools.

lib/mcp/tools/index.ts (1)

19-19: LGTM!

The import and registration of artist tools follows the existing patterns in this file. The alphabetical placement (Artists before ArtistSocials) maintains consistency.

Also applies to: 28-28

lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.ts (5)

1-15: LGTM!

Mock setup is correctly structured. The wrapper pattern (...args: unknown[]) => mockFn(...args) ensures the mock reference is properly captured, and mocks are hoisted before the module import as required by vitest.


17-31: LGTM!

The test setup is well-structured. Capturing the registered handler via the mock's callback allows direct handler testing. The beforeEach properly clears mocks for test isolation.


33-66: LGTM!

The registration test appropriately validates the tool name and description. The success path test correctly verifies the integration: arguments are passed to createArtistInDb, and the response follows the MCP tool result structure.


68-93: LGTM!

The test correctly validates the room copying flow: when active_conversation_id is provided, copyRoom is invoked with the source conversation and the new artist's account_id, and the response includes the new room ID.


95-148: LGTM!

The test coverage is thorough:

  • organization_id propagation is correctly validated
  • Both error paths are tested: null return from createArtistInDb (business failure) and thrown exceptions (unexpected errors)

Good error handling coverage for the MCP tool.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +44 to +49
// Step 1: Create the account
const account = await insertAccount({ name });

// Step 2: Create account info for the account
const accountInfo = await insertAccountInfo({ account_id: account.id });
if (!accountInfo) return null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing null check for insertAccount result.

If insertAccount returns null or undefined (instead of throwing), accessing account.id on line 48 will cause a TypeError. Add a null check to handle this case consistently with other steps.

🐛 Proposed fix
     // Step 1: Create the account
     const account = await insertAccount({ name });
+    if (!account) return null;

     // Step 2: Create account info for the account
     const accountInfo = await insertAccountInfo({ account_id: account.id });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Step 1: Create the account
const account = await insertAccount({ name });
// Step 2: Create account info for the account
const accountInfo = await insertAccountInfo({ account_id: account.id });
if (!accountInfo) return null;
// Step 1: Create the account
const account = await insertAccount({ name });
if (!account) return null;
// Step 2: Create account info for the account
const accountInfo = await insertAccountInfo({ account_id: account.id });
if (!accountInfo) return null;
🤖 Prompt for AI Agents
In `@lib/artists/createArtistInDb.ts` around lines 44 - 49, The code calls
insertAccount and immediately uses account.id without checking for a
null/undefined return; update createArtistInDb (around the insertAccount call)
to validate the account result and return null (or handle error) if
insertAccount returned null/undefined before calling insertAccountInfo,
mirroring the existing accountInfo null-check pattern so you don't attempt to
access account.id when account is falsy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants