All files / client/src/hooks use-compilation.ts

100% Statements 15/15
90% Branches 9/10
71.42% Functions 5/7
100% Lines 15/15

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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                                      92x   92x                           92x 92x 45x   5x 5x   5x 5x   5x 5x       40x             92x 10x     92x                                        
import { useCompileAndRun, CompileAndRunParams } from "./use-compile-and-run";
import { useRef, useEffect } from "react";
import type { MutableRefObject } from "react";
import type { SetState } from "./use-compile-and-run";
import type { IncomingArduinoMessage } from "@/types/websocket";
 
// compilation-only parameters (simulation inputs are injected with no-ops)
type UseCompilationParams = Omit<
  CompileAndRunParams,
  |
    "serialEventQueueRef"
    | "pendingPinConflicts"
    | "setPendingPinConflicts"
    | "isModified"
    | "handleCompileAndStart"
    | "startSimulationRef"
> & {
  // original compile-only extras
  startSimulation?: () => void;
  setHasCompiledOnce?: SetState<boolean>;
 
  // when provided by a caller (e.g. arduino-simulator page) the compile
  // hook will use these to start the simulation over the network. this
  // keeps the helper convenient for pure-compile scenarios while still
  // allowing the integrated compile+run page to function correctly.
  sendMessage?: (message: IncomingArduinoMessage) => void;
  sendMessageImmediate?: (message: IncomingArduinoMessage) => boolean;
  // when provided, handleCompileAndStart will delegate the simulation start
  // to the ref's current function (populated by the simulation hook) so the
  // correct simulationTimeout is used instead of the compile-hook's default.
  startSimulationRef?: MutableRefObject<(() => void) | null>;
};
 
export function useCompilation(params: UseCompilationParams) {
  // merge passed compile params with harmless defaults for simulation fields
  const emptyQueueRef = useRef<Array<{ payload: IncomingArduinoMessage; receivedAt: number }>>([]);
 
  const merged = useCompileAndRun({
    ...params,
    sendMessage: params.sendMessage ?? (() => {}),
    sendMessageImmediate: params.sendMessageImmediate,
    serialEventQueueRef: emptyQueueRef,
    pendingPinConflicts: [],
    setPendingPinConflicts: () => {},
    isModified: false,
    handleCompileAndStart: () => {},
    startSimulationRef: params.startSimulationRef ?? ({ current: null } as MutableRefObject<(() => void) | null>),
  });
 
  // notify caller of compile successes in the old style and trigger
  // optional external simulation start *after* compilation status updates.
  const startCalled = useRef(false);
  useEffect(() => {
    if (merged.compilationStatus === "success") {
      // update external flags
      params.setHasCompiledOnce?.(true);
      params.setIsModified?.(false);
      // trigger external startSimulation only once per success
      Eif (!startCalled.current && typeof params.startSimulation === "function") {
        startCalled.current = true;
        // defer to microtask so that compilationStatus has updated for callers
        Promise.resolve().then(() => {
          params.startSimulation?.();
        });
      }
    } else {
      startCalled.current = false;
    }
  }, [merged.compilationStatus, params]);
 
  // mirror the original Public API exactly
  // wrap handleCompileAndStart so that external callers (tests / legacy
  // users) can pass their own startSimulation callback.
  const handleCompileAndStart = () => {
    merged.handleCompileAndStart();
  };
 
  return {
    compilationStatus: merged.compilationStatus,
    setCompilationStatus: merged.setCompilationStatus,
    arduinoCliStatus: merged.arduinoCliStatus,
    setArduinoCliStatus: merged.setArduinoCliStatus,
    hasCompilationErrors: merged.hasCompilationErrors,
    setHasCompilationErrors: merged.setHasCompilationErrors,
    compilerErrors: merged.compilerErrors,
    setCompilerErrors: merged.setCompilerErrors,
    lastCompilationResult: merged.lastCompilationResult,
    setLastCompilationResult: merged.setLastCompilationResult,
    cliOutput: merged.cliOutput,
    setCliOutput: merged.setCliOutput,
    compileMutation: merged.compileMutation,
    handleCompile: merged.handleCompile,
    handleCompileAndStart,
    handleClearCompilationOutput: merged.handleClearCompilationOutput,
    clearOutputs: merged.clearOutputs,
  };
}