import assert from "node:assert" ; import { ReadonlyDeep , } from "type-fest" ; import Camera from "uvc-control" ; import CameraFactory from "./camera-factory.js" ; import CameraHelperFactory from "./camera-helper-factory.js" ; import CommandHandlers from "./command-handlers.js" ; import Output from "./output.js" ; import { RuntimeConfiguration , } from "./runtime-configurator.js" ; import { CommandHandlerArgumentCameraHelper , CommandHandlerArgumentTypes , CommandHandlerLookup , } from "./types/command.js" ; export default class CommandManager { constructor ( private readonly output , private readonly cameraFactory , private readonly cameraHelperFactory , private readonly commandHandlers ) { assert . strictEqual ( arguments . length , 4 ) ; assert ( typeof this . output === "object" ) ; assert ( typeof this . cameraFactory === "object" ) ; assert ( typeof this . cameraHelperFactory === "object" ) ; assert ( typeof this . commandHandlers === "object" ) ; } async execute ( runtimeConfig ) { this . output . verbose ( "Parsed arguments:" , JSON . stringify ( runtimeConfig , null , 2 ) ) ; const commandName = runtimeConfig . cmd ; const commandHandlerExists = await this . commandHandlers . has ( commandName ) ; if ( ! commandHandlerExists ) { this . output . error ( "Unknown command:" , commandName ) ; return ; } let camera = null ; const closeCamera = async ( ) => { if ( camera ) { await camera . close ( ) ; } } ; const commandArguments = await this . commandHandlers . getArguments ( commandName ) ; if ( commandArguments . includes ( CommandHandlerArgumentCameraHelper ) ) { const { vendor , product , address , } = runtimeConfig ; assert ( typeof vendor === "number" ) ; assert ( typeof product === "number" ) ; assert ( typeof address === "number" ) ; camera = await this . cameraFactory . get ( vendor , product , address ) ; } try { const argumentValues = commandArguments . filter ( ( commandArgument ) => commandArgument !== CommandHandlerArgumentCameraHelper ) . map ( ( commandArgument ) => ( runtimeConfig as CommandHandlerLookup ) [ commandArgument ] ) ; if ( commandArguments . includes ( CommandHandlerArgumentCameraHelper ) ) { assert ( camera !== null ) ; const cameraHelper = await this . cameraHelperFactory . get ( camera ) ; argumentValues . unshift ( cameraHelper ) ; } const output = await this . commandHandlers . execute ( commandName , ... argumentValues ) ; if ( typeof output !== "undefined" ) { const json = JSON . stringify ( output , null , 2 ) ; this . output . normal ( json ) ; } await closeCamera ( ) ; } catch ( error ) { try { await closeCamera ( ) ; } catch { } throw error ; } } }