/** * Dependency-injection provider for the UI ports. * * Chooses real Tauri adapters vs mocks based on `VITE_USE_MOCK` (any truthy * value → mocks). Components consume gateways via {@link useGateways} and never * construct adapters or call `invoke()` themselves. */ import { createContext, useContext, useMemo, type ReactNode, } from "react"; import type { Gateways } from "@/ports"; import { createTauriGateways } from "@/adapters"; import { createMockGateways } from "@/adapters/mock"; const GatewaysContext = createContext(null); /** Whether the mock adapters should be used (env-driven, overridable in tests). */ export function shouldUseMock(): boolean { const flag = import.meta.env.VITE_USE_MOCK; return flag === "1" || flag === "true"; } /** Resolves the gateway set for the current environment. */ export function resolveGateways(): Gateways { return shouldUseMock() ? createMockGateways() : createTauriGateways(); } interface DIProviderProps { children: ReactNode; /** Optional explicit gateways (used by tests/Storybook). */ gateways?: Gateways; } export function DIProvider({ children, gateways }: DIProviderProps) { const value = useMemo(() => gateways ?? resolveGateways(), [gateways]); return ( {children} ); } /** Hook returning the injected gateways. Throws if used outside the provider. */ export function useGateways(): Gateways { const ctx = useContext(GatewaysContext); if (!ctx) { throw new Error("useGateways must be used within a "); } return ctx; }