diff --git a/docs/ARCHITECTURE_GUIDE.md b/docs/ARCHITECTURE_GUIDE.md index 11c44efd3..9a0bf3a2c 100644 --- a/docs/ARCHITECTURE_GUIDE.md +++ b/docs/ARCHITECTURE_GUIDE.md @@ -75,7 +75,7 @@ export type DayDietRepository = { limit?: number, ) => Promise fetchDayDietById: (dayId: DayDiet['id']) => Promise - insertDayDiet: (newDay: NewDayDiet) => Promise + insertDayDiet: (newDay: NewDayDiet) => Promise updateDayDietById: ( dayId: DayDiet['id'], newDay: NewDayDiet, @@ -84,6 +84,8 @@ export type DayDietRepository = { } ``` +`insertDayDiet` returns the created `DayDiet` and surfaces errors instead of returning `null`; callers should treat failures as exceptions rather than nullable results. + ### `infrastructure/supabase/supabaseDayGateway.ts` ```ts @@ -253,8 +255,8 @@ export async function fetchTargetDay( await dayRepository.fetchDayDietByUserIdAndTargetDay(userId, targetDay); } -export async function insertDayDiet(dayDiet: NewDayDiet): Promise { - await showPromise( +export async function insertDayDiet(dayDiet: NewDayDiet): Promise { + return await showPromise( dayRepository.insertDayDiet(dayDiet), { loading: 'Criando dia de dieta...', @@ -501,8 +503,8 @@ User operations with toast integration. ```typescript const dayRepository = createDayDietRepository() -export async function insertDayDiet(dayDiet: NewDayDiet): Promise { - await showPromise( +export async function insertDayDiet(dayDiet: NewDayDiet): Promise { + return await showPromise( dayRepository.insertDayDiet(dayDiet), { loading: 'Criando dia de dieta...', diff --git a/src/modules/diet/day-diet/application/usecases/dayUseCases.ts b/src/modules/diet/day-diet/application/usecases/dayUseCases.ts index 75888cf33..53b1dbcde 100644 --- a/src/modules/diet/day-diet/application/usecases/dayUseCases.ts +++ b/src/modules/diet/day-diet/application/usecases/dayUseCases.ts @@ -175,13 +175,11 @@ export function createDayUseCases(deps: { }, { context: 'user-action' }, ) - if (insertedDayDiet !== null) { - dayCacheStore.upsertToCache(insertedDayDiet) - } + dayCacheStore.upsertToCache(insertedDayDiet) return insertedDayDiet } catch (error) { logging.error('DayDiet insert error:', error) - return null + throw error } }, updateDayDietById: async (dayId: DayDiet['id'], dayDiet: NewDayDiet) => { diff --git a/src/modules/diet/day-diet/domain/dayDietGateway.ts b/src/modules/diet/day-diet/domain/dayDietGateway.ts index f2b18ff74..7d092a4ff 100644 --- a/src/modules/diet/day-diet/domain/dayDietGateway.ts +++ b/src/modules/diet/day-diet/domain/dayDietGateway.ts @@ -15,7 +15,7 @@ export type DayGateway = { limit?: number, ) => Promise fetchDayDietById: (dayId: DayDiet['id']) => Promise - insertDayDiet: (newDay: NewDayDiet) => Promise + insertDayDiet: (newDay: NewDayDiet) => Promise updateDayDietById: ( dayId: DayDiet['id'], newDay: NewDayDiet, diff --git a/src/modules/diet/day-diet/domain/dayDietRepository.ts b/src/modules/diet/day-diet/domain/dayDietRepository.ts index 38720ae45..b9c01aca6 100644 --- a/src/modules/diet/day-diet/domain/dayDietRepository.ts +++ b/src/modules/diet/day-diet/domain/dayDietRepository.ts @@ -15,7 +15,7 @@ export type DayRepository = { limit?: number, ) => Promise fetchDayDietById: (dayId: DayDiet['id']) => Promise - insertDayDiet: (newDay: NewDayDiet) => Promise // TODO: Remove nullability from insertDay + insertDayDiet: (newDay: NewDayDiet) => Promise updateDayDietById: ( dayId: DayDiet['id'], newDay: NewDayDiet, diff --git a/src/modules/diet/day-diet/infrastructure/guest/guestDayGateway.ts b/src/modules/diet/day-diet/infrastructure/guest/guestDayGateway.ts index f3c2e818d..0bc3d7d87 100644 --- a/src/modules/diet/day-diet/infrastructure/guest/guestDayGateway.ts +++ b/src/modules/diet/day-diet/infrastructure/guest/guestDayGateway.ts @@ -75,7 +75,7 @@ async function fetchDayDietsByUserIdBeforeDate( return dayDiets } -async function insertDayDiet(newDay: NewDayDiet): Promise { +async function insertDayDiet(newDay: NewDayDiet): Promise { const dayDiet = promoteDayDiet(newDay, { id: generateDayId() }) updateGuestDatabase((db) => ({ diff --git a/src/modules/diet/day-diet/infrastructure/supabase/supabaseDayGateway.ts b/src/modules/diet/day-diet/infrastructure/supabase/supabaseDayGateway.ts index 994d9c430..4c7b2641b 100644 --- a/src/modules/diet/day-diet/infrastructure/supabase/supabaseDayGateway.ts +++ b/src/modules/diet/day-diet/infrastructure/supabase/supabaseDayGateway.ts @@ -371,7 +371,7 @@ async function fetchDayDietsByUserIdBeforeDate( return dayDTOs.map((dto) => dayToDomain(dto)) } -async function insertDayDiet(newDay: NewDayDiet): Promise { +async function insertDayDiet(newDay: NewDayDiet): Promise { const newDayDTO = dayToInsertDTO(newDay) const { data: dayDTO, error } = await supabase @@ -384,6 +384,14 @@ async function insertDayDiet(newDay: NewDayDiet): Promise { throw wrapErrorWithStack(error) } + // Supabase types mark `data` as non-null after `.single()`, but keep a runtime guard for safety. + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (dayDTO === null) { + throw new Error('Failed to insert day diet: Supabase returned no data', { + cause: { newDayDTO }, + }) + } + return dayToDomain(dayDTO) } diff --git a/src/modules/diet/day-diet/tests/infrastructure/guestDayGateway.test.ts b/src/modules/diet/day-diet/tests/infrastructure/guestDayGateway.test.ts new file mode 100644 index 000000000..c70c868a7 --- /dev/null +++ b/src/modules/diet/day-diet/tests/infrastructure/guestDayGateway.test.ts @@ -0,0 +1,37 @@ +import { beforeEach, describe, expect, it } from 'vitest' + +import { createNewDayDiet } from '~/modules/diet/day-diet/domain/dayDiet' +import { createDefaultMeals } from '~/modules/diet/day-diet/domain/defaultMeals' +import { createGuestDayGateway } from '~/modules/diet/day-diet/infrastructure/guest/guestDayGateway' +import { + getGuestDatabase, + resetGuestDatabase, +} from '~/shared/guest/guestDatabase' + +describe('guestDayGateway.insertDayDiet', () => { + beforeEach(() => { + resetGuestDatabase() + }) + + it('returns the created day diet and persists it', async () => { + const gateway = createGuestDayGateway() + const userId = getGuestDatabase().user.uuid + const newDayDiet = createNewDayDiet({ + target_day: '2099-01-02', + user_id: userId, + meals: createDefaultMeals(), + }) + + const insertedDayDiet = await gateway.insertDayDiet(newDayDiet) + + expect(insertedDayDiet).toMatchObject({ + target_day: '2099-01-02', + user_id: userId, + __type: 'DayDiet', + }) + expect(typeof insertedDayDiet.id).toBe('number') + expect( + getGuestDatabase().dayDiets.some((day) => day.id === insertedDayDiet.id), + ).toBe(true) + }) +})