/**
 * Copyright (c) 2021 Expo, Inc.
 * Copyright (c) 2018 Drifty Co.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */ import Debug from 'debug' ; import * as fs from 'fs' ; import type * as net from 'net' ; import type { LockdownCommand , LockdownResponse } from '../protocol/lockdown' ; import { isLockdownResponse , LockdownProtocolClient } from '../protocol/lockdown' ; import { ResponseError , ServiceClient } from './client' ; const debug = Debug ( 'expo:xdl:ios:lib:client:mobile_image_mounter' ) ; export type MIMMountResponse = LockdownResponse ; export interface MIMMessage extends LockdownCommand { ImageType : string ; } export interface MIMLookupResponse extends LockdownResponse { ImageSignature ? : string ; } export interface MIMUploadCompleteResponse extends LockdownResponse { Status : 'Complete' ; } export interface MIMUploadReceiveBytesResponse extends LockdownResponse { Status : 'ReceiveBytesAck' ; } function isMIMUploadCompleteResponse ( resp ) { return resp . Status === 'Complete' ; } function isMIMUploadReceiveBytesResponse ( resp ) { return resp . Status === 'ReceiveBytesAck' ; } export class MobileImageMounterClient extends ServiceClient < LockdownProtocolClient < MIMMessage > > { constructor ( socket ) { super ( socket , new LockdownProtocolClient ( socket ) ) ; } async mountImage ( imagePath , imageSig ) { debug ( `mountImage: ${ imagePath }` ) ; const resp = await this . protocolClient . sendMessage ( { Command : 'MountImage' , ImagePath : imagePath , ImageSignature : imageSig , ImageType : 'Developer' } ) ; if ( ! isLockdownResponse ( resp ) || resp . Status !== 'Complete' ) { throw new ResponseError ( `There was an error mounting ${ imagePath } on device` , resp ) ; } } async uploadImage ( imagePath , imageSig ) { debug ( `uploadImage: ${ imagePath }` ) ; const imageSize = fs . statSync ( imagePath ) . size ; return this . protocolClient . sendMessage ( { Command : 'ReceiveBytes' , ImageSize : imageSize , ImageSignature : imageSig , ImageType : 'Developer' } , ( resp , resolve , reject ) => { if ( isMIMUploadReceiveBytesResponse ( resp ) ) { const imageStream = fs . createReadStream ( imagePath ) ; imageStream . pipe ( this . protocolClient . socket , { end : false } ) ; imageStream . on ( 'error' , err => reject ( err ) ) ; } else if ( isMIMUploadCompleteResponse ( resp ) ) { resolve ( ) ; } else { reject ( new ResponseError ( `There was an error uploading image ${ imagePath } to the device` , resp ) ) ; } } ) ; } async lookupImage ( ) { debug ( 'lookupImage' ) ; return this . protocolClient . sendMessage < MIMLookupResponse > ( { Command : 'LookupImage' , ImageType : 'Developer' } ) ; } }