refactor: separate Nakama provider concerns into context, refs, and state modules

- Extracted context contract to `contexts.ts` (NakamaContextType)
- Added strongly typed internal provider refs in `refs.ts`
  - socketRef: React.RefObject<Socket | null>
  - gameMetadataRef: React.RefObject<GameMetadata | null>
- Added `NakamaProviderState` in `states.ts` for React-managed provider state
  - session, socket, matchId, matchmakerTicket
- Refactored NakamaProvider to use new modular structure
  - Replaced scattered useState/useRef with structured internal state + refs
  - Updated onMatchData to use MatchDataMessage model
  - Replaced deprecated MutableRefObject typing with RefObject
  - Cleaned update patterns using `updateState` helper
- Updated imports to use new models and context structure
- Improved separation of responsibilities:
  - models = pure domain types
  - context = exposed provider API
  - refs = internal mutable runtime refs
  - state = provider-managed reactive state
- Ensured all Nakama provider functions fully typed and consistent with TS

This refactor improves clarity, type safety, and maintainability for the
Nakama real-time multiplayer provider.
This commit is contained in:
2025-12-04 18:56:48 +05:30
parent 51b051b34c
commit ab9dd42689
10 changed files with 239 additions and 86 deletions

View File

@@ -0,0 +1,38 @@
import {
Client,
Session,
Socket,
} from "@heroiclabs/nakama-js";
import {
ApiMatch,
ApiLeaderboardRecordList,
// @ts-ignore
} from "@heroiclabs/nakama-js/dist/api.gen"
import {
GameMetadata,
MatchDataMessage,
} from './models'
export interface NakamaContextType {
client: Client;
socket: Socket | null;
session: Session | null;
matchId: string | null;
loginOrRegister(username?: string): Promise<void>;
logout(): Promise<void>;
joinMatchmaker(gameMetadata: GameMetadata): Promise<string>;
exitMatchmaker(gameMetadata: GameMetadata): Promise<void>;
joinMatch(matchId: string): Promise<void>;
sendMatchData(matchId: string, op: number, data: object): void;
onMatchData(cb: (msg: MatchDataMessage) => void): void;
getLeaderboardTop(): Promise<ApiLeaderboardRecordList>;
listOpenMatches(): Promise<ApiMatch[]>;
}