Skip to content
Merged
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
19 changes: 11 additions & 8 deletions src/di/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import {
createTelemetry,
type TelemetryModule,
} from '~/modules/observability/application/telemetry'
import { initializeSentry } from '~/modules/observability/infrastructure/sentry/sentry'
import { createSentryService } from '~/modules/observability/infrastructure/sentry/sentry'
import {
createProfile,
type ProfileModule,
Expand Down Expand Up @@ -163,15 +163,20 @@ function createModeAwareUserRepository(deps: {
}
}

const sharedSentryService = createSentryService()

function createAppTelemetry(): TelemetryModule {
return createTelemetry({
sentryService: sharedSentryService,
})
}

export function createContainer(
overrides: Partial<ContainerInstances> = {},
): Readonly<Container> {
return createRoot((dispose) => {
const telemetryUseCases =
overrides.telemetryUseCases ??
createTelemetry({
initializeSentry,
})
overrides.telemetryUseCases ?? createAppTelemetry()

Comment thread
marcuscastelo marked this conversation as resolved.
let guestUseCasesRef: GuestUseCases | null = overrides.guestUseCases ?? null

Expand Down Expand Up @@ -370,9 +375,7 @@ let bootstrapTelemetry: TelemetryModule | null = null

function getBootstrapTelemetry() {
if (bootstrapTelemetry === null) {
bootstrapTelemetry = createTelemetry({
initializeSentry,
})
bootstrapTelemetry = createAppTelemetry()
}

return bootstrapTelemetry
Expand Down
15 changes: 3 additions & 12 deletions src/di/useCases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,11 @@ import { createUserUseCases } from '~/modules/user/application/usecases/userUseC
import { type UserRepository } from '~/modules/user/domain/userRepository'
import { createGuestUserRepository } from '~/modules/user/infrastructure/guest/guestUserRepository'
import { createSupabaseUserRepository } from '~/modules/user/infrastructure/supabase/supabaseUserRepository'
import {
createWeightChartUseCases,
type WeightChartUseCases,
} from '~/modules/weight/application/chart/weightChartUseCases'
import {
createWeightUseCases,
type WeightUseCases,
} from '~/modules/weight/application/weight/usecases/weightUseCases'
import { createWeightChartUseCases } from '~/modules/weight/application/chart/weightChartUseCases'
import { createWeightUseCases } from '~/modules/weight/application/weight/usecases/weightUseCases'
import { createGuestUseCases } from '~/shared/guest/guestUseCases'

export type AppMode = 'guest' | 'normal'

// Re-export use-case types for consumers
export type { WeightChartUseCases, WeightUseCases }
type AppMode = 'guest' | 'normal'

// TODO: Refactor global DI so that we don't need to switch repositories like this
// Issue URL: https://github.com/marcuscastelo/macroflows/issues/1440
Expand Down
54 changes: 49 additions & 5 deletions src/modules/auth/infrastructure/supabase/supabaseAuthGateway.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AuthChangeEvent, Session } from '@supabase/supabase-js'
import type { AuthChangeEvent, Session, User } from '@supabase/supabase-js'

import type {
AuthSession,
Expand All @@ -10,7 +10,51 @@ import type { AuthGateway } from '~/modules/auth/domain/authGateway'
import { supabase } from '~/shared/supabase/supabase'
import { logging } from '~/shared/utils/logging'

import { supabaseAuthMapper } from './supabaseAuthMapper'
function mapUserToDomain(user: User | null): AuthUser | null {
if (user === null) return null

return {
id: user.id,
email: user.email ?? 'unknown@example.com',
emailConfirmedAt: user.email_confirmed_at ?? undefined,
lastSignInAt: user.last_sign_in_at ?? undefined,
createdAt:
user.created_at !== '' ? user.created_at : new Date().toISOString(),
updatedAt:
user.updated_at !== undefined && user.updated_at !== ''
? user.updated_at
: new Date().toISOString(),
userMetadata: user.user_metadata,
appMetadata: user.app_metadata,
}
}

function mapSessionToDomain(session: Session | null): AuthSession | null {
if (session === null) return null

return {
access_token: session.access_token,
refresh_token: session.refresh_token,
expires_at: session.expires_at ?? 0,
token_type: session.token_type,
user: {
id: session.user.id,
email: session.user.email ?? '',
email_confirmed_at: session.user.email_confirmed_at ?? undefined,
last_sign_in_at: session.user.last_sign_in_at ?? undefined,
created_at:
session.user.created_at !== ''
? session.user.created_at
: new Date().toISOString(),
updated_at:
session.user.updated_at !== undefined && session.user.updated_at !== ''
? session.user.updated_at
: new Date().toISOString(),
user_metadata: session.user.user_metadata,
app_metadata: session.user.app_metadata,
},
}
}

export function createSupabaseAuthGateway(): AuthGateway {
return {
Expand All @@ -23,7 +67,7 @@ export function createSupabaseAuthGateway(): AuthGateway {
throw new Error('Failed to get session', { cause: error })
}

return supabaseAuthMapper.mapSessionToDomain(data.session)
return mapSessionToDomain(data.session)
} catch (error) {
logging.error('SupabaseAuthRepository getSession error:', error)
throw error
Expand All @@ -38,7 +82,7 @@ export function createSupabaseAuthGateway(): AuthGateway {
throw new Error('Failed to get user', { cause: error })
}

return supabaseAuthMapper.mapUserToDomain(data.user)
return mapUserToDomain(data.user)
} catch (error) {
logging.error('SupabaseAuthRepository getUser error:', error)
throw error
Expand Down Expand Up @@ -101,7 +145,7 @@ export function createSupabaseAuthGateway(): AuthGateway {
data: { subscription },
} = supabase.auth.onAuthStateChange(
(event: AuthChangeEvent, session: Session | null) => {
callback(event, supabaseAuthMapper.mapSessionToDomain(session))
callback(event, mapSessionToDomain(session))
},
)

Expand Down
65 changes: 0 additions & 65 deletions src/modules/auth/infrastructure/supabase/supabaseAuthMapper.ts

This file was deleted.

14 changes: 8 additions & 6 deletions src/modules/diet/day-diet/application/usecases/dayUseCases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ import {
type DayDiet,
type NewDayDiet,
} from '~/modules/diet/day-diet/domain/dayDiet'
import {
createDayDietRepository,
type DayRepository,
} from '~/modules/diet/day-diet/infrastructure/dayDietRepository'
import { initializeDayDietRealtime } from '~/modules/diet/day-diet/infrastructure/supabase/realtime'
import { type DayRepository } from '~/modules/diet/day-diet/domain/dayDietRepository'
import { createDayDietRepository } from '~/modules/diet/day-diet/infrastructure/dayDietRepository'
import { createDayDietRealtimeService } from '~/modules/diet/day-diet/infrastructure/supabase/realtime'
import { showPromise } from '~/modules/toast/application/toastManager'
import { type User } from '~/modules/user/domain/user'
import { getTodayYYYYMMDD } from '~/shared/utils/date/dateUtils'
Expand All @@ -36,12 +34,16 @@ import { logging } from '~/shared/utils/logging'
export function createDayUseCases(deps: {
authUseCases: () => AuthUseCases
dayRepository?: DayRepository
createDayDietRealtimeService?: typeof createDayDietRealtimeService
}) {
return createRoot(() => {
const authUseCases = () => deps.authUseCases()
const dayChangeStore = createDayChangeStore()
const dayStateStore = createDayStateStore()
const dayCacheStore = createDayCacheStore()
const realtimeService = (
deps.createDayDietRealtimeService ?? createDayDietRealtimeService
)()

const dayRepository = deps.dayRepository ?? createDayDietRepository()

Expand All @@ -55,7 +57,7 @@ export function createDayUseCases(deps: {
dayStateStore.setTargetDay(today)
}

initializeDayDietRealtime({
realtimeService.initializeDayDietRealtime({
onInsert(newDayDiet) {
dayCacheStore.upsertToCache(newDayDiet)
},
Expand Down
2 changes: 0 additions & 2 deletions src/modules/diet/day-diet/infrastructure/dayDietRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,3 @@ export function createDayDietRepository(deps?: {
await getGateway().deleteDayDietById(dayId),
}
}

export type { DayRepository }

This file was deleted.

77 changes: 44 additions & 33 deletions src/modules/diet/day-diet/infrastructure/supabase/realtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,61 @@ import {
type DayDiet,
dayDietSchema,
} from '~/modules/diet/day-diet/domain/dayDiet'
import { SUPABASE_TABLE_DAYS } from '~/modules/diet/day-diet/infrastructure/supabase/constants'
import { registerSubapabaseRealtimeCallback } from '~/shared/supabase/supabase'
import { logging } from '~/shared/utils/logging'

let initialized = false
const SUPABASE_TABLE_DAYS = 'days'
let dayDietRealtimeInitialized = false

export function initializeDayDietRealtime(callbacks: {
type DayDietRealtimeCallbacks = {
onInsert: (newDayDiet: DayDiet) => void
onUpdate: (newDayDiet: DayDiet) => void
onDelete: (oldDayDiet: DayDiet) => void
}): void {
if (initialized) {
return
}
logging.debug(`Day diet realtime initialized!`)
initialized = true
registerSubapabaseRealtimeCallback(
SUPABASE_TABLE_DAYS,
dayDietSchema,
(event) => {
logging.debug(`Event:`, event)

switch (event.eventType) {
case 'INSERT': {
if (event.new !== undefined) {
callbacks.onInsert(event.new)
}

export function createDayDietRealtimeService() {
function initializeDayDietRealtime(
callbacks: DayDietRealtimeCallbacks,
): void {
if (dayDietRealtimeInitialized) {
return
}

logging.debug(`Day diet realtime initialized!`)
dayDietRealtimeInitialized = true
registerSubapabaseRealtimeCallback(
Comment thread
marcuscastelo marked this conversation as resolved.
SUPABASE_TABLE_DAYS,
dayDietSchema,
(event) => {
logging.debug(`Event:`, event)

switch (event.eventType) {
case 'INSERT': {
if (event.new !== undefined) {
callbacks.onInsert(event.new)
}
break
}
break
}

case 'UPDATE': {
if (event.new) {
callbacks.onUpdate(event.new)
case 'UPDATE': {
if (event.new) {
callbacks.onUpdate(event.new)
}
break
}
break
}

case 'DELETE': {
if (event.old) {
callbacks.onDelete(event.old)
case 'DELETE': {
if (event.old) {
callbacks.onDelete(event.old)
}
break
}
break
}
}
},
)
},
)
}

return {
initializeDayDietRealtime,
}
}
Loading
Loading