microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
8d9de4a2454fec3afb774de950c38df23884bc88

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/common/node/childProcess.ts

160lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as nodeChildProcess from "child_process";
5import { ErrorHelper } from "../error/errorHelper";
6import { InternalErrorCode } from "../error/internalErrorCode";
7
8// Uncomment the following lines to record all spawned processes executions
9// import {Recorder} from "../../../test/resources/processExecution/recorder";
10// Recorder.installGlobalRecorder();
11
12export interface IExecResult {
13 process: nodeChildProcess.ChildProcess;
14 outcome: Promise<string>;
15}
16
17export interface ISpawnResult {
18 spawnedProcess: nodeChildProcess.ChildProcess;
19 stdin: NodeJS.WritableStream;
20 stdout: NodeJS.ReadableStream;
21 stderr: NodeJS.ReadableStream;
22 outcome: Promise<void>;
23}
24
25interface IExecOptions {
26 cwd?: string;
27 stdio?: any;
28 env?: any;
29 encoding?: string;
30 timeout?: number;
31 maxBuffer?: number;
32 killSignal?: string;
33}
34
35interface ISpawnOptions {
36 cwd?: string;
37 stdio?: any;
38 env?: any;
39 detached?: boolean;
40}
41
42export class ChildProcess {
43 public static ERROR_TIMEOUT_MILLISECONDS = 300;
44 private childProcess: typeof nodeChildProcess;
45
46 constructor({ childProcess = nodeChildProcess } = {}) {
47 this.childProcess = childProcess;
48 }
49
50 public exec(command: string, options: IExecOptions = {}): Promise<IExecResult> {
51 let outcome: Promise<string>;
52 let process: nodeChildProcess.ChildProcess;
53 return new Promise<IExecResult>(resolveRes => {
54 outcome = new Promise<string>((resolve, reject) => {
55 process = this.childProcess.exec(
56 command,
57 options,
58 // eslint-disable-next-line @typescript-eslint/no-unused-vars
59 (error: Error, stdout: string, stderr: string) => {
60 if (error) {
61 reject(
62 ErrorHelper.getNestedError(
63 error,
64 InternalErrorCode.CommandFailed,
65 command,
66 ),
67 );
68 } else {
69 resolve(stdout);
70 }
71 },
72 );
73 });
74 resolveRes({ process: process, outcome: outcome });
75 });
76 }
77
78 public execToString(command: string, options: IExecOptions = {}): Promise<string> {
79 return this.exec(command, options).then(result =>
80 result.outcome.then(stdout => stdout.toString()),
81 );
82 }
83
84 public execFileSync(
85 command: string,
86 args: string[] = [],
87 options: IExecOptions = {},
88 ): Buffer | string {
89 return this.childProcess.execFileSync(command, args, options);
90 }
91
92 public spawn(
93 command: string,
94 args: string[] = [],
95 options: ISpawnOptions = {},
96 showStdOutputsOnError: boolean = false,
97 ): ISpawnResult {
98 const spawnedProcess = this.childProcess.spawn(command, args, options);
99 let outcome: Promise<void> = new Promise((resolve, reject) => {
100 spawnedProcess.once("error", (error: any) => {
101 reject(error);
102 });
103
104 const stderrChunks: string[] = [];
105 const stdoutChunks: string[] = [];
106
107 spawnedProcess.stderr.on("data", data => {
108 stderrChunks.push(data.toString());
109 });
110
111 spawnedProcess.stdout.on("data", data => {
112 stdoutChunks.push(data.toString());
113 });
114
115 spawnedProcess.once("exit", (code: number) => {
116 if (code === 0) {
117 resolve();
118 } else {
119 const commandWithArgs = command + " " + args.join(" ");
120 if (showStdOutputsOnError) {
121 let details = "";
122 if (stdoutChunks.length > 0) {
123 details = details.concat(
124 `\n\tSTDOUT: ${stdoutChunks[stdoutChunks.length - 1]}`,
125 );
126 }
127 if (stderrChunks.length > 0) {
128 details = details.concat(`\n\tSTDERR: ${stderrChunks.join("\n\t")}`);
129 }
130 if (details === "") {
131 details = "STDOUT and STDERR are empty!";
132 }
133 reject(
134 ErrorHelper.getInternalError(
135 InternalErrorCode.CommandFailedWithDetails,
136 commandWithArgs,
137 details,
138 ),
139 );
140 } else {
141 reject(
142 ErrorHelper.getInternalError(
143 InternalErrorCode.CommandFailed,
144 commandWithArgs,
145 code,
146 ),
147 );
148 }
149 }
150 });
151 });
152 return {
153 spawnedProcess: spawnedProcess,
154 stdin: spawnedProcess.stdin,
155 stdout: spawnedProcess.stdout,
156 stderr: spawnedProcess.stderr,
157 outcome: outcome,
158 };
159 }
160}
161