import * as vscode from 'vscode'; import * as projectmanager from './ProjectManager'; import axios, { AxiosResponse , AxiosRequestConfig} from 'axios'; import * as fs from 'fs'; /** * @interface HttpProjectManager * * @description HTTP project manager client class let handling of an Edge.AI project data model stored remotly */ export class HttpProjectManager extends projectmanager.IProjectManager { private __project : any; public set _project(value: any) { this.__project = value; this._parsedProject = projectmanager.Project.deserialize(this.__project, this.uri); } public get _project(): any { return this.__project; } protected _parsedProject: projectmanager.Project | undefined; public get project(): projectmanager.Project { if(!this._parsedProject) throw new Error('No project set'); return this._parsedProject; } protected _onDidChangeProject: vscode.EventEmitter = new vscode.EventEmitter(); public onDidChangeProject : vscode.Event; private _jwtToken: string | undefined; public get jwtToken(): string { if(!this._jwtToken) throw new Error("Authentication token not set"); return this._jwtToken; } public set jwtToken(value: string) { this._jwtToken = value; } constructor(public backendBaseUrl: vscode.Uri){ super(backendBaseUrl); this.onDidChangeProject = this._onDidChangeProject.event; } /** * Inerithed methods */ public async connect(projectName: string): Promise { this.uri = vscode.Uri.joinPath( this.backendBaseUrl, "/2/projects/" + projectName ); } public async load(): Promise { const response : AxiosResponse = await axios.get(this.uri.toString(), { headers: { "Authorization": "Bearer " + this.jwtToken }}); this._project = response.data; this._onDidChangeProject.fire(this.project); } public async updateModel(modelId: string, name: string, stage: projectmanager.ModelStage | undefined, modelMetadata: any | undefined){ let patchedModel : any = { uuid: modelId }; if(name){ patchedModel["name"] = name; } if(stage){ patchedModel["stage"] = stage?.toString(); } if(modelMetadata){ patchedModel["model_metadata"] = modelMetadata; } const uri: vscode.Uri = vscode.Uri.joinPath(this.uri); const options: Object = { headers: { "Authorization": "Bearer " + this.jwtToken, "Content-Type": "application/json" } }; await axios.patch(uri.toString(), { models: [patchedModel] } , options); await this.load(); this._onDidChangeProject.fire(this.project); } /** * @description Not implemented */ newProject(projectId: string | undefined, name: string, description: string, owner: string, version: string) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ addModel(modelId: string, inputId: string, outputId: string, name: string, stage: projectmanager.ModelStage, inputType: projectmanager.InputType, modelType: projectmanager.ModelType, outputType: projectmanager.OutputType, trainingType: projectmanager.TrainingType, modelMetadata: any, inputTools: projectmanager.Tool[], outputTools: projectmanager.Tool[]) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ removeModel(modelId: string) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ addExperiment(modelId: string, experimentId: string, name: string, description: string, modelDevFile: String | null) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ updateExperiment(modelId: string, id: string, description: String, modelDevFile: String | null) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ removeExperiment(modelId: string, experimentId: string) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ addTest(modelId: string, experimentId: string, testId: string | undefined, name: string, modelFile: string | null) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ updateTest(modelId: string, testId: string, parameters: any, reports: string[] | undefined, outputs: string[] | undefined) { throw new Error('Method not implemented.'); } /** * @description Not implemented */ removeTest(modelId: string, experimentId: string, testId: string) { throw new Error('Method not implemented.'); } /** * Additional methods */ /** * @name getProjects * @description List remote user projects * * @returns Projects descriptors */ public async getProjects() : Promise> { const url: vscode.Uri = vscode.Uri.joinPath( this.backendBaseUrl, "/2/projects" ); const response : AxiosResponse = await axios.get(url.toString(), { headers: { "Authorization": "Bearer " + this.jwtToken }}); return response.data.map((rawProject: any) => projectmanager.Project.deserialize(rawProject, vscode.Uri.joinPath( url, rawProject.ai_project_name ))); } /** * @name getProject * @description Get remote user project * * @param projectName Project name to retrieve * @returns Projects descriptor */ public async getProject(projectName: string) : Promise { const url: vscode.Uri = vscode.Uri.joinPath( this.backendBaseUrl, "/2/projects/" + projectName ); const response : AxiosResponse = await axios.get(url.toString(), { headers: { "Authorization": "Bearer " + this.jwtToken }}); return projectmanager.Project.deserialize(response.data, vscode.Uri.joinPath( url, response.data.ai_project_name )); } /** * @name uploadLog * @description Upload acquisition zip folder for a model * * @param modelName Unique model name * @param logId Project name to retrieve * @param zipLog Project name to retrieve * @returns Projects descriptor */ public async uploadLog(modelName: string, logId: string, zipLog: vscode.Uri){ const uri: vscode.Uri = vscode.Uri.joinPath(this.uri, "models", modelName, "logs"); const options: Object = { maxContentLength: Infinity, maxBodyLength: Infinity, headers: { "Authorization": "Bearer " + this.jwtToken, "Content-Type": "application/octet-stream" }, params: { log_uuid : logId } }; await axios.post(uri.toString(), fs.createReadStream(zipLog.fsPath) ,options); await this.load(); this._onDidChangeProject.fire(this.project); } /** * @name downloadTestOutput * @description Download a test output * * @param modelName Model name * @param experimentName Experiment name * @param testName Test name * @param outputName Output name * @param outputStream Readable stream of output file */ public async downloadTestOutput(modelName: string, experimentName: string, testName: string, outputName: string, outputStream: fs.WriteStream){ const uri: vscode.Uri = vscode.Uri.joinPath(this.uri, "models", modelName, "experiments", experimentName, "tests", testName, "outputs", outputName); const options: AxiosRequestConfig = { headers: { "Authorization": "Bearer " + this.jwtToken } , responseType: "stream"}; const response = await axios.get(uri.toString(), options); const p = response.data.pipe(outputStream); await new Promise((resolve, reject)=> { p.on("close", resolve); p.on("error", reject); }); } }