Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 6, 2025

Infrastructure files were exporting individual helper functions alongside factories, leaking implementation details. This refactoring restricts exports to factory functions only.

Changes

recipeRepository.ts

  • Made 6 helper functions internal (fetchUserRecipes, fetchRecipeById, etc.)
  • Only createRecipeRepository() factory is exported

supabaseRecipeMapper.ts

  • Unexported internal DTO types (RecipeDTO, InsertRecipeDTO, UpdateRecipeDTO)
  • Retained supabaseRecipeMapper object export

realtime.ts

  • Wrapped functions in createRecipeRealtimeService() factory
  • Encapsulated initialized state within factory closure

No changes

  • supabaseRecipeGateway.ts already followed pattern
  • recipeCacheStore.ts intentionally exports signal store (not a helper function)

API Surface

Before:

// Multiple exports mixed with factory
export function createRecipeRepository(): RecipeRepository { ... }
export async function fetchUserRecipes(...) { ... }
export async function fetchRecipeById(...) { ... }
// ... more individual functions

After:

// Factory only
export function createRecipeRepository(): RecipeRepository {
  return {
    fetchUserRecipes,
    fetchRecipeById,
    // ... all functions as methods
  }
}

All consumers already use the factory pattern, so no breaking changes.

Original prompt

This section details on the original issue you should resolve

<issue_title>diet/recipe: Encapsulate infra exports — export only factories</issue_title>
<issue_description>## Summary

Refactor the diet/recipe module infrastructure to encapsulate implementation details: export only factory functions and keep helper functions file-local.

Part of #1403

Scope / Representative files

  • src/modules/diet/recipe/infrastructure/recipeRepository.ts
  • src/modules/diet/recipe/infrastructure/supabase/supabaseRecipeGateway.ts
  • src/modules/diet/recipe/infrastructure/supabase/supabaseRecipeMapper.ts
  • src/modules/diet/recipe/infrastructure/signals/recipeCacheStore.ts
  • src/modules/diet/recipe/infrastructure/supabase/realtime.ts

Deliverables

  • Export only factories (e.g., createRecipeRepository, createSupabaseRecipeGateway).
  • Update call-sites to use returned instances.
  • Ensure TypeScript/lint/tests pass.

Acceptance Criteria

  • No internal helper functions are exported from infra files.
    </issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link

vercel bot commented Dec 6, 2025

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

Project Deployment Preview Comments Updated (UTC)
macroflows Ready Ready Preview Comment Dec 6, 2025 6:39pm

…rt factories

Co-authored-by: marcuscastelo <27441558+marcuscastelo@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor diet/recipe to encapsulate infrastructure exports refactor(diet/recipe): Encapsulate infrastructure exports — export only factories Dec 6, 2025
Copilot AI requested a review from marcuscastelo December 6, 2025 18:41
@marcuscastelo marcuscastelo marked this pull request as ready for review December 6, 2025 19:02
Copilot AI review requested due to automatic review settings December 6, 2025 19:02
@marcuscastelo marcuscastelo merged commit 36a839f into marcuscastelo/issue1447-remove-shims Dec 6, 2025
10 checks passed
@marcuscastelo marcuscastelo deleted the copilot/refactor-diet-recipe-infra branch December 6, 2025 19:05
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the diet/recipe module infrastructure to improve encapsulation by restricting exports to factory functions only, aligning with the repository's Clean Architecture approach.

Key Changes:

  • Made 6 helper functions in recipeRepository.ts internal, exposing only createRecipeRepository() factory
  • Changed DTO types in supabaseRecipeMapper.ts from exported to internal (file-local)
  • Wrapped realtime service functions in createRecipeRealtimeService() factory

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/modules/diet/recipe/infrastructure/recipeRepository.ts Internalized 6 repository helper functions (fetchUserRecipes, fetchRecipeById, etc.), maintaining only factory export
src/modules/diet/recipe/infrastructure/supabase/supabaseRecipeMapper.ts Changed 3 DTO types (RecipeDTO, InsertRecipeDTO, UpdateRecipeDTO) from exported to internal
src/modules/diet/recipe/infrastructure/supabase/realtime.ts Wrapped setupRecipeRealtimeSubscription and initializeRecipeRealtime in createRecipeRealtimeService() factory, encapsulating initialized state in closure

Comment on lines +7 to 73
export function createRecipeRealtimeService() {
let initialized = false

/**
* Sets up granular realtime subscription for recipe changes
* @param onRecipeChange - Callback for granular updates with event details
*/
export function setupRecipeRealtimeSubscription(
onRecipeChange: (event: {
eventType: 'INSERT' | 'UPDATE' | 'DELETE'
old?: Recipe
new?: Recipe
}) => void,
): void {
registerSubapabaseRealtimeCallback(
SUPABASE_TABLE_RECIPES,
recipeSchema,
onRecipeChange,
)
}

export function initializeRecipeRealtime(): void {
if (initialized) {
return
/**
* Sets up granular realtime subscription for recipe changes
* @param onRecipeChange - Callback for granular updates with event details
*/
function setupRecipeRealtimeSubscription(
onRecipeChange: (event: {
eventType: 'INSERT' | 'UPDATE' | 'DELETE'
old?: Recipe
new?: Recipe
}) => void,
): void {
registerSubapabaseRealtimeCallback(
SUPABASE_TABLE_RECIPES,
recipeSchema,
onRecipeChange,
)
}
logging.debug(`Recipe realtime initialized!`)
initialized = true
registerSubapabaseRealtimeCallback(
SUPABASE_TABLE_RECIPES,
recipeSchema,
(event) => {
logging.debug(`Event:`, event)

switch (event.eventType) {
case 'INSERT': {
if (event.new !== undefined) {
recipeCacheStore.upsertToCache(event.new)
function initializeRecipeRealtime(): void {
if (initialized) {
return
}
logging.debug(`Recipe realtime initialized!`)
initialized = true
registerSubapabaseRealtimeCallback(
SUPABASE_TABLE_RECIPES,
recipeSchema,
(event) => {
logging.debug(`Event:`, event)

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

case 'UPDATE': {
if (event.new) {
recipeCacheStore.upsertToCache(event.new)
case 'UPDATE': {
if (event.new) {
recipeCacheStore.upsertToCache(event.new)
}
break
}
break
}

case 'DELETE': {
if (event.old) {
recipeCacheStore.removeFromCache({ by: 'id', value: event.old.id })
case 'DELETE': {
if (event.old) {
recipeCacheStore.removeFromCache({
by: 'id',
value: event.old.id,
})
}
break
}
break
}
}
},
)
},
)
}

return {
setupRecipeRealtimeSubscription,
initializeRecipeRealtime,
}
}
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

The realtime service has been wrapped in a factory pattern (createRecipeRealtimeService()), which is inconsistent with other realtime services in the codebase (e.g., day-diet/infrastructure/supabase/realtime.ts and macro-profile/infrastructure/supabase/realtime.ts).

These other modules export the initialization function directly with module-level singleton initialized state, not wrapped in a factory. The factory pattern here could break singleton behavior if multiple instances are created, potentially causing duplicate subscriptions.

Recommendation: Export initializeRecipeRealtime and setupRecipeRealtimeSubscription directly with module-level initialized state to match the established pattern in the codebase.

Copilot uses AI. Check for mistakes.
@marcuscastelo marcuscastelo linked an issue Dec 6, 2025 that may be closed by this pull request
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.

diet/recipe: Encapsulate infra exports — export only factories

2 participants