// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for details. import * as cp from "child_process"; import { promisify } from "util"; import * as semver from "semver"; import * as commandExists from "command-exists"; export const executeCommand = promisify(cp.exec); export const normizeStr = (str: string): string => str.replace(/\r\n/g, "\n"); export const createNotFoundMessage = (str: string): string => `Command not found. Make sure ${str} is installed`; export const createVersionErrorMessage = (str: string): string => `Version check failed. Make sure ${str} is working correctly`; interface IBasicCheckResult { exists: boolean; /** * - 0 : within range * - 1 : gt range * - -1 : lt range*/ versionCompare?: 0 | 1 | -1; } export const basicCheck = async (arg: { command: string; getVersion?: () => Promise; versionRange?: semver.Range | string; }): Promise => { const result = { exists: true, } as IBasicCheckResult; if (!commandExists.sync(arg.command)) { result.exists = false; return result; } const version = await arg.getVersion?.(); if (!version) { return result; } if (!arg.versionRange) { result.versionCompare = 0; return result; } result.versionCompare = semver.gtr(version, arg.versionRange) ? 1 : semver.ltr(version, arg.versionRange) ? -1 : 0; return result; }; /** Run command and parse output with regex. Get first capturing group. If command does not exist - throws an error. */ export const parseVersion = async ( command: string, reg?: RegExp, prop: "stdout" | "stderr" = "stdout", ): Promise => { const data = await executeCommand(command).catch(() => {}); if (!data) { return null; } const text = normizeStr(data[prop]); return semver.coerce(reg ? reg.exec(text)?.[0] : text); }; // change typescript lib to es2019 ? export const fromEntries = ( entries: Iterable, ): Record => [...entries].reduce((obj, [key, val]) => { obj[key] = val; return obj; }, {} as Record); // export const flatten = (ary: any[]): unknown[] =>