microsoft/vscode-react-native
Publicmirrored from https://github.com/microsoft/vscode-react-nativeAvailable
src/extension/services/validationService/util.ts
85lines · modeblame
c7856462Heniker4 years ago | 1 | // Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | // Licensed under the MIT license. See LICENSE file in the project root for details. | |
| 3 | | |
| 4 | import * as cp from "child_process"; | |
| 5 | import { promisify } from "util"; | |
| 6 | import * as semver from "semver"; | |
948a0d44Heniker4 years ago | 7 | import * as commandExists from "command-exists"; |
c7856462Heniker4 years ago | 8 | |
| 9 | export const executeCommand = promisify(cp.exec); | |
| 10 | export const normizeStr = (str: string): string => str.replace(/\r\n/g, "\n"); | |
| 11 | | |
| 12 | export const createNotFoundMessage = (str: string): string => | |
| 13 | `Command not found. Make sure ${str} is installed`; | |
| 14 | export const createVersionErrorMessage = (str: string): string => | |
| 15 | `Version check failed. Make sure ${str} is working correctly`; | |
| 16 | | |
948a0d44Heniker4 years ago | 17 | interface IBasicCheckResult { |
| 18 | exists: boolean; | |
| 19 | /** | |
| 20 | * - 0 : within range | |
| 21 | * - 1 : gt range | |
| 22 | * - -1 : lt range*/ | |
| 23 | versionCompare?: 0 | 1 | -1; | |
| 24 | } | |
| 25 | | |
| 26 | export const basicCheck = async (arg: { | |
| 27 | command: string; | |
| 28 | getVersion?: () => Promise<string | null | undefined>; | |
| 29 | versionRange?: semver.Range | string; | |
| 30 | }): Promise<IBasicCheckResult> => { | |
| 31 | const result = { | |
| 32 | exists: true, | |
| 33 | } as IBasicCheckResult; | |
| 34 | | |
| 35 | if (!commandExists.sync(arg.command)) { | |
| 36 | result.exists = false; | |
| 37 | return result; | |
| 38 | } | |
| 39 | | |
| 40 | const version = await arg.getVersion?.(); | |
| 41 | | |
| 42 | if (!version) { | |
| 43 | return result; | |
| 44 | } | |
| 45 | | |
| 46 | if (!arg.versionRange) { | |
| 47 | result.versionCompare = 0; | |
| 48 | return result; | |
| 49 | } | |
| 50 | | |
| 51 | result.versionCompare = semver.gtr(version, arg.versionRange) | |
| 52 | ? 1 | |
| 53 | : semver.ltr(version, arg.versionRange) | |
| 54 | ? -1 | |
| 55 | : 0; | |
| 56 | | |
| 57 | return result; | |
| 58 | }; | |
| 59 | | |
| 60 | /** Run command and parse output with regex. Get first capturing group. If command does not exist - throws an error. */ | |
| 61 | export const parseVersion = async ( | |
c7856462Heniker4 years ago | 62 | command: string, |
948a0d44Heniker4 years ago | 63 | reg?: RegExp, |
c7856462Heniker4 years ago | 64 | prop: "stdout" | "stderr" = "stdout", |
| 65 | ): Promise<semver.SemVer | null> => { | |
68c29472Heniker4 years ago | 66 | const data = await executeCommand(command).catch(() => {}); |
| 67 | | |
| 68 | if (!data) { | |
| 69 | return null; | |
| 70 | } | |
| 71 | | |
948a0d44Heniker4 years ago | 72 | const text = normizeStr(data[prop]); |
| 73 | return semver.coerce(reg ? reg.exec(text)?.[1] : text); | |
c7856462Heniker4 years ago | 74 | }; |
| 75 | | |
| 76 | // change typescript lib to es2019 ? | |
| 77 | export const fromEntries = <T = any, J extends PropertyKey = PropertyKey>( | |
| 78 | entries: Iterable<readonly [J, T]>, | |
| 79 | ): Record<J, T> => | |
| 80 | [...entries].reduce((obj, [key, val]) => { | |
| 81 | obj[key] = val; | |
| 82 | return obj; | |
| 83 | }, {} as Record<J, T>); | |
| 84 | | |
| 85 | // export const flatten = (ary: any[]): unknown[] => |