codify-plugin-test 0.0.52 → 0.0.53-beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,17 @@
1
1
  import Ajv from 'ajv';
2
- import { IpcMessageSchema, MessageCmd, SpawnStatus, SudoRequestDataSchema } from 'codify-schemas';
2
+ import { CommandRequestDataSchema, IpcMessageSchema, MessageCmd } from 'codify-schemas';
3
3
  import { nanoid } from 'nanoid';
4
- import { fork, spawn } from 'node:child_process';
5
- import path from 'node:path';
6
- import { CodifyTestUtils } from './test-utils.js';
4
+ import { fork } from 'node:child_process';
7
5
  import fs from 'node:fs/promises';
8
6
  import * as os from 'node:os';
7
+ import path from 'node:path';
8
+ import { spawnSafe } from './spawn.js';
9
+ import { CodifyTestUtils } from './test-utils.js';
9
10
  const ajv = new Ajv.default({
10
11
  strict: true
11
12
  });
12
13
  const ipcMessageValidator = ajv.compile(IpcMessageSchema);
13
- const sudoRequestValidator = ajv.compile(SudoRequestDataSchema);
14
+ const commandRequestValidator = ajv.compile(CommandRequestDataSchema);
14
15
  export class PluginProcess {
15
16
  childProcess;
16
17
  constructor(pluginPath) {
@@ -70,23 +71,23 @@ export class PluginProcess {
70
71
  if (!ipcMessageValidator(message)) {
71
72
  throw new Error(`Invalid message from plugin. ${JSON.stringify(message, null, 2)}`);
72
73
  }
73
- if (message.cmd === MessageCmd.SUDO_REQUEST) {
74
+ if (message.cmd === MessageCmd.COMMAND_REQUEST) {
74
75
  const { data, requestId } = message;
75
- if (!sudoRequestValidator(data)) {
76
- throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
76
+ if (!commandRequestValidator(data)) {
77
+ throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(commandRequestValidator.errors, null, 2)}`);
77
78
  }
78
79
  const { command, options } = data;
79
- const result = await sudoSpawn(command, options);
80
+ const result = await spawnSafe(command, options);
80
81
  process.send({
81
- cmd: MessageCmd.SUDO_REQUEST + '_Response',
82
+ cmd: MessageCmd.COMMAND_REQUEST + '_Response',
82
83
  data: result,
83
84
  requestId,
84
85
  });
85
86
  }
86
87
  if (message.cmd === MessageCmd.PRESS_KEY_TO_CONTINUE_REQUEST) {
87
88
  const { data, requestId } = message;
88
- if (!sudoRequestValidator(data)) {
89
- throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
89
+ if (!commandRequestValidator(data)) {
90
+ throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(commandRequestValidator.errors, null, 2)}`);
90
91
  }
91
92
  process.send({
92
93
  cmd: MessageCmd.PRESS_KEY_TO_CONTINUE_REQUEST + '_Response',
@@ -113,32 +114,4 @@ export class PluginProcess {
113
114
  });
114
115
  }
115
116
  }
116
- async function sudoSpawn(cmd, opts) {
117
- return new Promise((resolve) => {
118
- const output = [];
119
- const _cmd = `sudo ${cmd}`;
120
- const _process = spawn(`source ~/.zshrc; ${_cmd}`, [], {
121
- ...opts,
122
- shell: 'zsh',
123
- stdio: ['ignore', 'pipe', 'pipe'],
124
- });
125
- const { stderr, stdout } = _process;
126
- stdout.setEncoding('utf8');
127
- stderr.setEncoding('utf8');
128
- stdout.on('data', (data) => {
129
- output.push(data.toString());
130
- });
131
- stderr.on('data', (data) => {
132
- output.push(data.toString());
133
- });
134
- stdout.pipe(process.stdout);
135
- stderr.pipe(process.stderr);
136
- _process.on('close', (code) => {
137
- resolve({
138
- data: output.join(''),
139
- status: code === 0 ? SpawnStatus.SUCCESS : SpawnStatus.ERROR,
140
- });
141
- });
142
- });
143
- }
144
117
  //# sourceMappingURL=plugin-process.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-process.js","sourceRoot":"","sources":["../src/plugin-process.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-process.js","sourceRoot":"","sources":["../src/plugin-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare enum Shell {
2
+ ZSH = "zsh",
3
+ BASH = "bash",
4
+ SH = "sh",
5
+ KSH = "ksh",
6
+ CSH = "csh",
7
+ FISH = "fish"
8
+ }
9
+ export declare const ShellUtils: {
10
+ getShell(): Shell | undefined;
11
+ getDefaultShell(): string;
12
+ };
package/dist/shell.js ADDED
@@ -0,0 +1,37 @@
1
+ export var Shell;
2
+ (function (Shell) {
3
+ Shell["ZSH"] = "zsh";
4
+ Shell["BASH"] = "bash";
5
+ Shell["SH"] = "sh";
6
+ Shell["KSH"] = "ksh";
7
+ Shell["CSH"] = "csh";
8
+ Shell["FISH"] = "fish";
9
+ })(Shell || (Shell = {}));
10
+ export const ShellUtils = {
11
+ getShell() {
12
+ const shell = process.env.SHELL || '';
13
+ if (shell.endsWith('bash')) {
14
+ return Shell.BASH;
15
+ }
16
+ if (shell.endsWith('zsh')) {
17
+ return Shell.ZSH;
18
+ }
19
+ if (shell.endsWith('sh')) {
20
+ return Shell.SH;
21
+ }
22
+ if (shell.endsWith('csh')) {
23
+ return Shell.CSH;
24
+ }
25
+ if (shell.endsWith('ksh')) {
26
+ return Shell.KSH;
27
+ }
28
+ if (shell.endsWith('fish')) {
29
+ return Shell.FISH;
30
+ }
31
+ return undefined;
32
+ },
33
+ getDefaultShell() {
34
+ return process.env.SHELL;
35
+ }
36
+ };
37
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,KAOX;AAPD,WAAY,KAAK;IACf,oBAAW,CAAA;IACX,sBAAa,CAAA;IACb,kBAAS,CAAA;IACT,oBAAW,CAAA;IACX,oBAAW,CAAA;IACX,sBAAa,CAAA;AACf,CAAC,EAPW,KAAK,KAAL,KAAK,QAOhB;AAGD,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,QAAQ;QACN,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QAEtC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC,IAAI,CAAA;QACnB,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC,GAAG,CAAA;QAClB,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,EAAE,CAAA;QACjB,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC,GAAG,CAAA;QAClB,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC,GAAG,CAAA;QAClB,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC,IAAI,CAAA;QACnB,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,eAAe;QACb,OAAO,OAAO,CAAC,GAAG,CAAC,KAAM,CAAC;IAC5B,CAAC;CACF,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { SpawnStatus } from 'codify-schemas';
2
+ export interface SpawnResult {
3
+ status: SpawnStatus;
4
+ exitCode: number;
5
+ data: string;
6
+ }
7
+ export interface SpawnOptions {
8
+ cwd?: string;
9
+ env?: Record<string, unknown>;
10
+ interactive?: boolean;
11
+ requiresRoot?: boolean;
12
+ stdin?: boolean;
13
+ }
14
+ export declare function spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
package/dist/spawn.js ADDED
@@ -0,0 +1,58 @@
1
+ import * as pty from '@homebridge/node-pty-prebuilt-multiarch';
2
+ import { SpawnStatus } from 'codify-schemas';
3
+ import stripAnsi from 'strip-ansi';
4
+ import { Shell, ShellUtils } from './shell.js';
5
+ export function spawnSafe(cmd, options) {
6
+ if (cmd.toLowerCase().includes('sudo')) {
7
+ throw new Error('Command must not include sudo');
8
+ }
9
+ process.stdout.write(`Running command: ${options?.requiresRoot ? 'sudo' : ''} ${cmd}` + (options?.cwd ? `(${options?.cwd})` : ''));
10
+ return new Promise((resolve) => {
11
+ const output = [];
12
+ const historyIgnore = ShellUtils.getShell() === Shell.ZSH ? { HISTORY_IGNORE: '*' } : { HISTIGNORE: '*' };
13
+ const env = {
14
+ ...process.env, ...options?.env,
15
+ TERM_PROGRAM: 'codify',
16
+ COMMAND_MODE: 'unix2003',
17
+ COLORTERM: 'truecolor',
18
+ ...historyIgnore
19
+ };
20
+ const initialCols = process.stdout.columns ?? 80;
21
+ const initialRows = process.stdout.rows ?? 24;
22
+ const command = options?.requiresRoot ? `sudo ${cmd}` : cmd;
23
+ const args = options?.interactive ? ['-i', '-c', command] : ['-c', command];
24
+ const mPty = pty.spawn(ShellUtils.getDefaultShell(), args, {
25
+ ...options,
26
+ cols: initialCols,
27
+ rows: initialRows,
28
+ env
29
+ });
30
+ mPty.onData((data) => {
31
+ process.stdout.write(data);
32
+ output.push(data.toString());
33
+ });
34
+ const resizeListener = () => {
35
+ const { columns, rows } = process.stdout;
36
+ mPty.resize(columns, rows);
37
+ };
38
+ const stdinListener = (data) => {
39
+ mPty.write(data.toString());
40
+ };
41
+ process.stdout.on('resize', resizeListener);
42
+ if (options?.stdin) {
43
+ process.stdin.on('data', stdinListener);
44
+ }
45
+ mPty.onExit((result) => {
46
+ process.stdout.off('resize', resizeListener);
47
+ if (options?.stdin) {
48
+ process.stdin.off('data', stdinListener);
49
+ }
50
+ resolve({
51
+ status: result.exitCode === 0 ? SpawnStatus.SUCCESS : SpawnStatus.ERROR,
52
+ exitCode: result.exitCode,
53
+ data: stripAnsi(output.join('\n').trim()),
54
+ });
55
+ });
56
+ });
57
+ }
58
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-test",
3
- "version": "0.0.52",
3
+ "version": "0.0.53-beta1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -16,12 +16,14 @@
16
16
  "dependencies": {
17
17
  "ajv": "^8.12.0",
18
18
  "ajv-formats": "^3.0.1",
19
- "codify-schemas": "1.0.77",
19
+ "codify-schemas": "1.0.86-beta5",
20
20
  "lodash.matches": "^4.6.0",
21
21
  "lodash.differencewith": "4.5.0",
22
22
  "lodash.unionby": "^4.8.0",
23
23
  "nanoid": "^5.0.9",
24
- "chalk": "^5.4.1"
24
+ "chalk": "^5.4.1",
25
+ "@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
26
+ "strip-ansi": "^7.1.2"
25
27
  },
26
28
  "devDependencies": {
27
29
  "@oclif/prettier-config": "^0.2.1",
@@ -37,7 +39,7 @@
37
39
  "tsx": "^4.7.3",
38
40
  "typescript": "^5",
39
41
  "vitest": "^1.4.0",
40
- "codify-plugin-lib": "1.0.171"
42
+ "codify-plugin-lib": "1.0.182-beta9"
41
43
  },
42
44
  "engines": {
43
45
  "node": ">=18.0.0"
@@ -1,28 +1,34 @@
1
1
  import Ajv from 'ajv';
2
2
  import {
3
- ApplyRequestData, ImportRequestData, ImportResponseData,
3
+ ApplyRequestData,
4
+ CommandRequestData,
5
+ CommandRequestDataSchema,
6
+ ImportRequestData,
7
+ ImportResponseData,
4
8
  InitializeResponseData,
5
9
  IpcMessageSchema,
6
10
  IpcMessageV2,
7
- MessageCmd, PlanRequestData, PlanResponseData,
8
- SpawnStatus,
9
- SudoRequestData,
10
- SudoRequestDataSchema, ValidateRequestData, ValidateResponseData
11
+ MessageCmd,
12
+ PlanRequestData,
13
+ PlanResponseData,
14
+ ValidateRequestData,
15
+ ValidateResponseData
11
16
  } from 'codify-schemas';
12
17
  import { nanoid } from 'nanoid';
13
- import { ChildProcess, SpawnOptions, fork, spawn } from 'node:child_process';
18
+ import { ChildProcess, fork } from 'node:child_process';
19
+ import fs from 'node:fs/promises';
20
+ import * as os from 'node:os';
14
21
  import path from 'node:path';
15
22
 
23
+ import { spawnSafe } from './spawn.js';
16
24
  import { CodifyTestUtils } from './test-utils.js';
17
- import fs from 'node:fs/promises';
18
- import * as os from 'node:os';
19
25
 
20
26
  const ajv = new Ajv.default({
21
27
  strict: true
22
28
  });
23
29
 
24
30
  const ipcMessageValidator = ajv.compile(IpcMessageSchema);
25
- const sudoRequestValidator = ajv.compile(SudoRequestDataSchema);
31
+ const commandRequestValidator = ajv.compile(CommandRequestDataSchema);
26
32
 
27
33
  export class PluginProcess {
28
34
  childProcess: ChildProcess
@@ -108,17 +114,17 @@ export class PluginProcess {
108
114
  throw new Error(`Invalid message from plugin. ${JSON.stringify(message, null, 2)}`);
109
115
  }
110
116
 
111
- if (message.cmd === MessageCmd.SUDO_REQUEST) {
117
+ if (message.cmd === MessageCmd.COMMAND_REQUEST) {
112
118
  const { data, requestId } = message;
113
- if (!sudoRequestValidator(data)) {
114
- throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
119
+ if (!commandRequestValidator(data)) {
120
+ throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(commandRequestValidator.errors, null, 2)}`);
115
121
  }
116
122
 
117
- const { command, options } = data as unknown as SudoRequestData;
118
- const result = await sudoSpawn(command, options);
123
+ const { command, options } = data as unknown as CommandRequestData;
124
+ const result = await spawnSafe(command, options);
119
125
 
120
126
  process.send(<IpcMessageV2>{
121
- cmd: MessageCmd.SUDO_REQUEST + '_Response',
127
+ cmd: MessageCmd.COMMAND_REQUEST + '_Response',
122
128
  data: result,
123
129
  requestId,
124
130
  })
@@ -126,8 +132,8 @@ export class PluginProcess {
126
132
 
127
133
  if (message.cmd === MessageCmd.PRESS_KEY_TO_CONTINUE_REQUEST) {
128
134
  const { data, requestId } = message;
129
- if (!sudoRequestValidator(data)) {
130
- throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
135
+ if (!commandRequestValidator(data)) {
136
+ throw new Error(`Invalid sudo request from plugin. ${JSON.stringify(commandRequestValidator.errors, null, 2)}`);
131
137
  }
132
138
 
133
139
  process.send(<IpcMessageV2>{
@@ -160,59 +166,3 @@ export class PluginProcess {
160
166
  }
161
167
 
162
168
  }
163
-
164
- type CodifySpawnOptions = {
165
- cwd?: string;
166
- throws?: boolean,
167
- } & Omit<SpawnOptions, 'detached' | 'shell' | 'stdio'>
168
-
169
- /**
170
- *
171
- * @param cmd Command to run. Ex: `rm -rf`
172
- * @param opts Options for spawn
173
- *
174
- * @see promiseSpawn
175
- * @see spawn
176
- *
177
- * @returns SpawnResult { status: SUCCESS | ERROR; data: string }
178
- */
179
- async function sudoSpawn(
180
- cmd: string,
181
- opts: CodifySpawnOptions,
182
- ): Promise<{ data: string, status: SpawnStatus }> {
183
- return new Promise((resolve) => {
184
- const output: string[] = [];
185
-
186
- const _cmd = `sudo ${cmd}`;
187
-
188
- // Source start up shells to emulate a users environment vs. a non-interactive non-login shell script
189
- // Ignore all stdin
190
- const _process = spawn(`source ~/.zshrc; ${_cmd}`, [], {
191
- ...opts,
192
- shell: 'zsh',
193
- stdio: ['ignore', 'pipe', 'pipe'],
194
- });
195
-
196
- const { stderr, stdout } = _process
197
- stdout.setEncoding('utf8');
198
- stderr.setEncoding('utf8');
199
-
200
- stdout.on('data', (data) => {
201
- output.push(data.toString());
202
- })
203
-
204
- stderr.on('data', (data) => {
205
- output.push(data.toString());
206
- })
207
-
208
- stdout.pipe(process.stdout);
209
- stderr.pipe(process.stderr);
210
-
211
- _process.on('close', (code) => {
212
- resolve({
213
- data: output.join(''),
214
- status: code === 0 ? SpawnStatus.SUCCESS : SpawnStatus.ERROR,
215
- })
216
- })
217
- })
218
- }
package/src/shell.ts ADDED
@@ -0,0 +1,45 @@
1
+ export enum Shell {
2
+ ZSH = 'zsh',
3
+ BASH = 'bash',
4
+ SH = 'sh',
5
+ KSH = 'ksh',
6
+ CSH = 'csh',
7
+ FISH = 'fish',
8
+ }
9
+
10
+
11
+ export const ShellUtils = {
12
+ getShell(): Shell | undefined {
13
+ const shell = process.env.SHELL || '';
14
+
15
+ if (shell.endsWith('bash')) {
16
+ return Shell.BASH
17
+ }
18
+
19
+ if (shell.endsWith('zsh')) {
20
+ return Shell.ZSH
21
+ }
22
+
23
+ if (shell.endsWith('sh')) {
24
+ return Shell.SH
25
+ }
26
+
27
+ if (shell.endsWith('csh')) {
28
+ return Shell.CSH
29
+ }
30
+
31
+ if (shell.endsWith('ksh')) {
32
+ return Shell.KSH
33
+ }
34
+
35
+ if (shell.endsWith('fish')) {
36
+ return Shell.FISH
37
+ }
38
+
39
+ return undefined;
40
+ },
41
+
42
+ getDefaultShell(): string {
43
+ return process.env.SHELL!;
44
+ }
45
+ }
package/src/spawn.ts ADDED
@@ -0,0 +1,91 @@
1
+ import * as pty from '@homebridge/node-pty-prebuilt-multiarch';
2
+ import { SpawnStatus } from 'codify-schemas';
3
+ import stripAnsi from 'strip-ansi';
4
+
5
+ import { Shell, ShellUtils } from './shell.js';
6
+
7
+ export interface SpawnResult {
8
+ status: SpawnStatus;
9
+ exitCode: number;
10
+ data: string;
11
+ }
12
+
13
+ export interface SpawnOptions {
14
+ cwd?: string;
15
+ env?: Record<string, unknown>,
16
+ interactive?: boolean,
17
+ requiresRoot?: boolean,
18
+ stdin?: boolean,
19
+ }
20
+
21
+ export function spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult> {
22
+ if (cmd.toLowerCase().includes('sudo')) {
23
+ throw new Error('Command must not include sudo')
24
+ }
25
+
26
+ process.stdout.write(`Running command: ${options?.requiresRoot ? 'sudo' : ''} ${cmd}` + (options?.cwd ? `(${options?.cwd})` : ''))
27
+
28
+ return new Promise((resolve) => {
29
+ const output: string[] = [];
30
+ const historyIgnore = ShellUtils.getShell() === Shell.ZSH ? { HISTORY_IGNORE: '*' } : { HISTIGNORE: '*' };
31
+
32
+ // If TERM_PROGRAM=Apple_Terminal is set then ANSI escape characters may be included
33
+ // in the response.
34
+ const env = {
35
+ ...process.env, ...options?.env,
36
+ TERM_PROGRAM: 'codify',
37
+ COMMAND_MODE: 'unix2003',
38
+ COLORTERM: 'truecolor',
39
+ ...historyIgnore
40
+ }
41
+
42
+ // Initial terminal dimensions
43
+ const initialCols = process.stdout.columns ?? 80;
44
+ const initialRows = process.stdout.rows ?? 24;
45
+
46
+ const command = options?.requiresRoot ? `sudo ${cmd}` : cmd;
47
+ const args = options?.interactive ? ['-i', '-c', command] : ['-c', command]
48
+
49
+ // Run the command in a pty for interactivity
50
+ const mPty = pty.spawn(ShellUtils.getDefaultShell(), args, {
51
+ ...options,
52
+ cols: initialCols,
53
+ rows: initialRows,
54
+ env
55
+ });
56
+
57
+ mPty.onData((data) => {
58
+ process.stdout.write(data);
59
+ output.push(data.toString());
60
+ })
61
+
62
+ const resizeListener = () => {
63
+ const { columns, rows } = process.stdout;
64
+ mPty.resize(columns, rows);
65
+ }
66
+
67
+ const stdinListener = (data: any) => {
68
+ // console.log('stdinListener', data);
69
+ mPty.write(data.toString());
70
+ }
71
+
72
+ // Listen to resize events for the terminal window;
73
+ process.stdout.on('resize', resizeListener);
74
+ if (options?.stdin) {
75
+ process.stdin.on('data', stdinListener)
76
+ }
77
+
78
+ mPty.onExit((result) => {
79
+ process.stdout.off('resize', resizeListener);
80
+ if (options?.stdin) {
81
+ process.stdin.off('data', stdinListener);
82
+ }
83
+
84
+ resolve({
85
+ status: result.exitCode === 0 ? SpawnStatus.SUCCESS : SpawnStatus.ERROR,
86
+ exitCode: result.exitCode,
87
+ data: stripAnsi(output.join('\n').trim()),
88
+ })
89
+ })
90
+ })
91
+ }