Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions docs/ARCHITECTURE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export type DayDietRepository = {
limit?: number,
) => Promise<readonly DayDiet[]>
fetchDayDietById: (dayId: DayDiet['id']) => Promise<DayDiet | null>
insertDayDiet: (newDay: NewDayDiet) => Promise<DayDiet | null>
insertDayDiet: (newDay: NewDayDiet) => Promise<DayDiet>
updateDayDietById: (
dayId: DayDiet['id'],
newDay: NewDayDiet,
Expand All @@ -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
Expand Down Expand Up @@ -253,8 +255,8 @@ export async function fetchTargetDay(
await dayRepository.fetchDayDietByUserIdAndTargetDay(userId, targetDay);
}

export async function insertDayDiet(dayDiet: NewDayDiet): Promise<void> {
await showPromise(
export async function insertDayDiet(dayDiet: NewDayDiet): Promise<DayDiet> {
return await showPromise(
dayRepository.insertDayDiet(dayDiet),
{
loading: 'Criando dia de dieta...',
Expand Down Expand Up @@ -501,8 +503,8 @@ User operations with toast integration.
```typescript
const dayRepository = createDayDietRepository()

export async function insertDayDiet(dayDiet: NewDayDiet): Promise<void> {
await showPromise(
export async function insertDayDiet(dayDiet: NewDayDiet): Promise<DayDiet> {
return await showPromise(
dayRepository.insertDayDiet(dayDiet),
{
loading: 'Criando dia de dieta...',
Expand Down
6 changes: 2 additions & 4 deletions src/modules/diet/day-diet/application/usecases/dayUseCases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/diet/day-diet/domain/dayDietGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type DayGateway = {
limit?: number,
) => Promise<readonly DayDiet[]>
fetchDayDietById: (dayId: DayDiet['id']) => Promise<DayDiet | null>
insertDayDiet: (newDay: NewDayDiet) => Promise<DayDiet | null>
insertDayDiet: (newDay: NewDayDiet) => Promise<DayDiet>
updateDayDietById: (
dayId: DayDiet['id'],
newDay: NewDayDiet,
Expand Down
2 changes: 1 addition & 1 deletion src/modules/diet/day-diet/domain/dayDietRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type DayRepository = {
limit?: number,
) => Promise<readonly DayDiet[]>
fetchDayDietById: (dayId: DayDiet['id']) => Promise<DayDiet | null>
insertDayDiet: (newDay: NewDayDiet) => Promise<DayDiet | null> // TODO: Remove nullability from insertDay
insertDayDiet: (newDay: NewDayDiet) => Promise<DayDiet>
updateDayDietById: (
dayId: DayDiet['id'],
newDay: NewDayDiet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ async function fetchDayDietsByUserIdBeforeDate(
return dayDiets
}

async function insertDayDiet(newDay: NewDayDiet): Promise<DayDiet | null> {
async function insertDayDiet(newDay: NewDayDiet): Promise<DayDiet> {
const dayDiet = promoteDayDiet(newDay, { id: generateDayId() })

updateGuestDatabase((db) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ async function fetchDayDietsByUserIdBeforeDate(
return dayDTOs.map((dto) => dayToDomain(dto))
}

async function insertDayDiet(newDay: NewDayDiet): Promise<DayDiet | null> {
async function insertDayDiet(newDay: NewDayDiet): Promise<DayDiet> {
const newDayDTO = dayToInsertDTO(newDay)

const { data: dayDTO, error } = await supabase
Expand All @@ -384,6 +384,14 @@ async function insertDayDiet(newDay: NewDayDiet): Promise<DayDiet | null> {
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)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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)
})
})