import { injectable, inject } from 'inversify'; import { Library, LibraryService } from '../common/protocol/library-service'; import { CoreClientProvider } from './core-client-provider'; import { LibrarySearchReq, LibrarySearchResp, LibraryListReq, LibraryListResp, LibraryRelease, InstalledLibrary, LibraryInstallReq, LibraryInstallResp } from './cli-protocol/lib_pb'; import { ToolOutputServiceServer } from '../common/protocol/tool-output-service'; @injectable() export class LibraryServiceImpl implements LibraryService { @inject(CoreClientProvider) protected readonly coreClientProvider: CoreClientProvider; @inject(ToolOutputServiceServer) protected readonly toolOutputService: ToolOutputServiceServer; async search(options: { query?: string; }): Promise<{ items: Library[] }> { const { client, instance } = await this.coreClientProvider.getClient(); const listReq = new LibraryListReq(); listReq.setInstance(instance); const installedLibsResp = await new Promise((resolve, reject) => client.libraryList(listReq, (err, resp) => !!err ? reject(err) : resolve(resp))); const installedLibs = installedLibsResp.getLibrariesList(); const installedLibsIdx = new Map(); installedLibs.forEach(l => installedLibsIdx.set(l.getName(), l)); const req = new LibrarySearchReq(); req.setQuery(options.query || ''); req.setInstance(instance); const resp = await new Promise((resolve, reject) => client.librarySearch(req, (err, resp) => !!err ? reject(err) : resolve(resp))); const items = resp.getSearchOutputList() .filter(item => !!item.getLatest()) .slice(0, 50) .map(item => { let installedVersion: string | undefined; const installed = installedLibsIdx.get(item.getName()); if (installed) { installedVersion = installed.getInstalled()!.getVersion(); } return toLibrary({ name: item.getName(), installable: true, installedVersion }, item.getLatest()!) }) return { items }; } async install(library: Library): Promise { const { client, instance } = await this.coreClientProvider.getClient(); const req = new LibraryInstallReq(); req.setInstance(instance); req.setName(library.name); req.setVersion(library.availableVersions[0]); const resp = client.libraryInstall(req); resp.on('data', (r: LibraryInstallResp) => { const prog = r.getProgress(); if (prog) { this.toolOutputService.publishNewOutput("library download", `downloading ${prog.getFile()}: ${prog.getCompleted()}%\n`) } }); await new Promise((resolve, reject) => { resp.on('end', resolve); resp.on('error', reject); }); } } function toLibrary(tpl: Partial, release: LibraryRelease): Library { return { name: "", installable: false, ...tpl, author: release.getAuthor(), availableVersions: [release.getVersion()], description: release.getSentence(), moreInfoLink: release.getWebsite(), summary: release.getParagraph() } }