All files / src/hooks useDebugApi.ts

88.23% Statements 30/34
77.77% Branches 7/9
100% Functions 1/1
88.23% Lines 30/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 561x 1x 1x 1x   1x   1x                                   1x 1x 6x 6x 6x 6x   3x 3x 3x 3x 3x 3x     3x   3x 3x 3x 3x 3x 3x 3x     3x 3x 6x 6x  
import { IS_DEV_BUILD } from '@/utils/isDevBuild';
import { useEffect } from 'react';
import { Logger } from '@/utils/Logger';
import { getErrorMessage } from '@/helpers/exceptions';
 
const logger = new Logger('useDebugApi');
 
/**
 * Attaches the `window.chempal` debug helpers while `enabled` is true, and
 * removes them again when it goes false.
 *
 * Dev builds always get the helpers (see `src/main.tsx`); this hook is what makes
 * them reachable in a normal build once the user unlocks advanced mode. The
 * module is imported dynamically so it stays a lazily-loaded chunk — nobody pays
 * for it until advanced mode is actually switched on.
 * @param enabled - Whether the helpers should be attached (i.e. advanced mode).
 * @returns Nothing; mutates the global `window` as a side effect.
 * @category Hooks
 * @example
 * ```tsx
 * const [advancedMode, setAdvancedMode] = useState(false);
 * useDebugApi(advancedMode);
 * // advancedMode → window.chempal is defined; toggling off removes it.
 * ```
 * @source
 */
export function useDebugApi(enabled: boolean): void {
  useEffect(() => {
    // Dev builds already expose the helpers unconditionally at startup; leave
    // them alone so leaving advanced mode doesn't strip a dev convenience.
    if (!enabled || IS_DEV_BUILD) return;
 
    let cancelled = false;
    void (async () => {
      try {
        const { exposeDebugApi } = await import('@/utils/debugConsole');
        if (!cancelled) exposeDebugApi();
      } catch (error) {
        logger.error(`Failed to expose the debug helpers: ${getErrorMessage(error)}`, { error });
      }
    })();
 
    return () => {
      cancelled = true;
      void (async () => {
        try {
          const { removeDebugApi } = await import('@/utils/debugConsole');
          removeDebugApi();
        } catch (error) {
          logger.error(`Failed to remove the debug helpers: ${getErrorMessage(error)}`, { error });
        }
      })();
    };
  }, [enabled]);
}