Skip to content

Conversation

@nbudin
Copy link
Contributor

@nbudin nbudin commented Dec 6, 2025

Summary

This PR completes a comprehensive migration from singleton patterns to context-based dependency injection for both Apollo Client and AuthenticityTokensManager throughout the application.

Changes Overview

Apollo Client Migration (~204 files)

Loaders and Actions:

  • Migrated all React Router loaders and actions to use apolloClientContext from the router context
  • Updated function signatures to use LoaderFunction<RouterContextProvider> and ActionFunction<RouterContextProvider>
  • All loaders/actions now get the client via context.get(apolloClientContext)

Component Code:

  • Updated all React components to use useApolloClient() hook from @apollo/client/react
  • Components now properly access the client through React's context system

Utility Functions:

  • Refactored conventionDayLoader to accept client as a parameter
  • Updated all call sites to pass the client from their respective contexts

AuthenticityTokensManager Migration (11 files)

React Components:

  • Migrated from AuthenticityTokensManager.instance singleton to useContext(AuthenticityTokensContext)
  • All components now properly access tokens through React's context system

Router Actions:

  • Updated to use context.get(authenticityTokensManagerContext) in action functions
  • Maintains consistency with the Apollo Client pattern

Documentation

Added comprehensive CLAUDE.md documentation covering:

  • Apollo Client usage patterns (loaders vs components)
  • Common mistakes and solutions
  • File organization and routing patterns
  • Testing considerations

Migration Statistics

  • Total files migrated: ~215 files
  • Apollo Client files: ~204 files
  • AuthenticityTokensManager files: 11 files
  • Commits: 9 commits

Breaking Changes

None - this is a refactoring that maintains the same public API.

Testing

  • ✅ All TypeScript compilation errors resolved
  • ✅ Zero files still using deprecated singleton patterns
  • ✅ Consistent patterns across entire codebase

Benefits

  1. Testability: Dependencies can now be easily mocked in tests
  2. Type Safety: Full TypeScript support with proper context types
  3. React Best Practices: Uses React's context system instead of global singletons
  4. Maintainability: Clear, consistent patterns documented in CLAUDE.md
  5. Future-Proof: Aligns with React Router v7 and modern React patterns

🤖 Generated with Claude Code

nbudin and others added 14 commits December 6, 2025 11:43
Replace global client exports with context-based client access across all
React Router loaders and actions. This ensures the Apollo Client instance
is properly obtained from the React Router context rather than using a
global export.

Changes:
- Replace `import { client } from 'useIntercodeApolloClient'` with
  `import { apolloClientContext } from 'AppContexts'`
- Update LoaderFunction and ActionFunction signatures to include
  RouterContextProvider type parameter
- Add context parameter destructuring to all loader/action functions
- Get client via `context.get(apolloClientContext)` at function start
- Update exported helper functions in EventAdmin/create.ts to accept
  client as parameter for consistency

Affects 87 files across loaders, actions, and route handlers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Complete the migration by updating remaining loader and action functions
that were still using the global client export. This ensures all React
Router data loading is consistent with the context-based approach.

Changes:
- Update 25 additional files with LoaderFunction/ActionFunction exports
- Replace global client imports with apolloClientContext
- Add RouterContextProvider type parameters to all loaders/actions
- Get client via context.get(apolloClientContext) in all functions
- Update EventAdmin/$id.ts helper functions to accept client parameter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace direct imports of the global client export with the useApolloClient()
hook from @apollo/client/react for all component-level usage. This completes
the migration away from the global client singleton pattern.

Changes:
- Replace 'import { client } from useIntercodeApolloClient' with
  'import { useApolloClient } from @apollo/client/react'
- Add 'const client = useApolloClient();' inside component/hook functions

This is separate from loader/action migrations which use apolloClientContext
from the React Router context.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
These two files were incorrectly changed to use the useApolloClient() hook
pattern in the previous commit, but they actually have loaders that need to
use the apolloClientContext pattern instead.

Fixes:
- OAuth/AuthorizedApplications.tsx: Use apolloClientContext in loader
- OrganizationAdmin/OrganizationIndex.tsx: Use apolloClientContext in loader

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
These files were incorrectly changed to import useApolloClient in the previous
commit, but they have loaders/actions that need to use apolloClientContext
instead.

Fixed files:
- EventProposals: AdminEditEventProposal, EditEventProposal, EventProposalHistory
- FormAdmin: FormAdminIndex, FormEditor
- OAuth: AuthorizationPrompt
- Reports: EventProvidedTickets, EventsByChoice, SignupSpy, index
- SignupModeration: UserRankedChoiceQueue
- SignupRoundsAdmin: SignupRoundsAdminPage, index
- StaffPositionAdmin: StaffPositionsTable
- UserActivityAlerts: UserActivityAlertsAdmin

All loaders and actions now correctly get the client from React Router context
using apolloClientContext.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Documents key patterns and conventions in the codebase, with special focus
on the Apollo Client usage patterns:
- Context-based client access in loaders/actions
- Hook-based client access in components
- Common mistakes to avoid
- File organization and routing patterns
- GraphQL, forms, modals, and other conventions

This will help AI assistants understand the codebase structure and follow
established patterns when making changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed 40+ files that were still importing the global client from
useIntercodeApolloClient. All loaders and actions now properly get the
Apollo Client from React Router context.

Key changes:
- Updated 40 files with loaders/actions to use apolloClientContext
- Refactored conventionDayLoader to accept client as parameter
- Updated call sites in ScheduleApp and AppRouter to pass client

This completes the migration away from the global client singleton pattern.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Migrated 11 files from using the deprecated AuthenticityTokensManager.instance
singleton pattern to properly using AuthenticityTokensContext.

Changes:
- React components now use useContext(AuthenticityTokensContext)
- Router actions use context.get(authenticityTokensManagerContext)
- All token access now goes through the context manager instance
- DevModeGraphiql updated to use useEffect instead of useCallback

Fixed files:
- Authentication: ForgotPasswordForm, ResetPassword, SignInForm, SignOutButton, SignUpForm
- BuiltInForms: FileUploadForm
- ClickwrapAgreement: index
- CmsAdmin: CmsGraphqlQueryForm
- DevModeGraphiql
- MyProfile: MyProfileForm
- OAuth: AuthorizationPrompt

This completes the migration away from singleton patterns to context-based
dependency injection.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed Rubocop errors by adding:
- Type description for ClientConfigurationType
- Field descriptions for all three fields
- Disabled GraphQL/ExtractType cop for the rails fields (style suggestion)

All Rubocop offenses resolved.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

Code Coverage Report: Only Changed Files listed

Package Coverage
Overall Coverage 🟢 50.57%

Minimum allowed coverage is 0%, this run produced 50.57%

@nbudin nbudin merged commit 694b00d into main Dec 8, 2025
17 checks passed
@nbudin nbudin deleted the middleware-client branch December 8, 2025 00:45
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