88 lines
2.2 KiB
TypeScript
88 lines
2.2 KiB
TypeScript
'use client';
|
|
|
|
import { useContext, useMemo } from 'react';
|
|
import { ContainerContext } from '../providers/ContainerProvider';
|
|
|
|
/**
|
|
* Primary injection hook - gets a service by token
|
|
*
|
|
* @example
|
|
* const leagueService = useInject(LEAGUE_SERVICE_TOKEN);
|
|
*/
|
|
export function useInject<T extends symbol>(token: T): T extends { type: infer U } ? U : unknown {
|
|
const container = useContext(ContainerContext);
|
|
|
|
if (!container) {
|
|
throw new Error('useInject must be used within ContainerProvider');
|
|
}
|
|
|
|
return useMemo(() => {
|
|
try {
|
|
return container.get(token) as T extends { type: infer U } ? U : unknown;
|
|
} catch (error) {
|
|
console.error(`Failed to resolve token ${token.toString()}:`, error);
|
|
throw error;
|
|
}
|
|
}, [container, token]);
|
|
}
|
|
|
|
/**
|
|
* Hook to get multiple services at once
|
|
*
|
|
* @example
|
|
* const [leagueService, driverService] = useInjectMany([
|
|
* LEAGUE_SERVICE_TOKEN,
|
|
* DRIVER_SERVICE_TOKEN
|
|
* ]);
|
|
*/
|
|
export function useInjectMany<T extends any[]>(tokens: symbol[]): T {
|
|
const container = useContext(ContainerContext);
|
|
|
|
if (!container) {
|
|
throw new Error('useInjectMany must be used within ContainerProvider');
|
|
}
|
|
|
|
return useMemo(() => {
|
|
return tokens.map(token => container.get(token)) as T;
|
|
}, [container, tokens]);
|
|
}
|
|
|
|
/**
|
|
* Hook to get all services of a given type (tag-based resolution)
|
|
*
|
|
* @example
|
|
* const allServices = useInjectAll<Service>('Service');
|
|
*/
|
|
export function useInjectAll<T>(serviceIdentifier: string | symbol): T[] {
|
|
const container = useContext(ContainerContext);
|
|
|
|
if (!container) {
|
|
throw new Error('useInjectAll must be used within ContainerProvider');
|
|
}
|
|
|
|
return useMemo(() => {
|
|
return container.getAll<T>(serviceIdentifier);
|
|
}, [container, serviceIdentifier]);
|
|
}
|
|
|
|
/**
|
|
* Hook for optional service injection (returns null if not found)
|
|
*
|
|
* @example
|
|
* const optionalService = useInjectOptional(MAYBE_SERVICE_TOKEN);
|
|
*/
|
|
export function useInjectOptional<T>(token: symbol): T | null {
|
|
const container = useContext(ContainerContext);
|
|
|
|
if (!container) {
|
|
return null;
|
|
}
|
|
|
|
return useMemo(() => {
|
|
try {
|
|
return container.get<T>(token);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}, [container, token]);
|
|
} |