@brunwig/mup-aws-beanstalk 0.8.4 → 0.8.6

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.
package/lib/utils.js CHANGED
@@ -3,89 +3,70 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.logStep = logStep;
7
- exports.shouldRebuild = shouldRebuild;
8
- exports.tmpBuildPath = tmpBuildPath;
9
- exports.names = names;
10
- exports.createUniqueName = createUniqueName;
11
- exports.getLogs = getLogs;
12
- exports.getNodeVersion = getNodeVersion;
13
- exports.selectPlatformArn = selectPlatformArn;
14
6
  exports.attachPolicies = attachPolicies;
15
- exports.getAccountId = getAccountId;
16
- exports.ensureRoleExists = ensureRoleExists;
17
- exports.ensureInstanceProfileExists = ensureInstanceProfileExists;
18
- exports.ensureRoleAdded = ensureRoleAdded;
19
- exports.ensurePoliciesAttached = ensurePoliciesAttached;
20
- exports.ensureInlinePolicyAttached = ensureInlinePolicyAttached;
7
+ exports.coloredStatusText = coloredStatusText;
8
+ exports.connectToInstance = connectToInstance;
9
+ exports.createUniqueName = createUniqueName;
10
+ exports.createVersionDescription = createVersionDescription;
21
11
  exports.ensureBucketExists = ensureBucketExists;
22
- exports.findBucketWithPrefix = findBucketWithPrefix;
23
12
  exports.ensureBucketPolicyAttached = ensureBucketPolicyAttached;
24
13
  exports.ensureCloudWatchRule = ensureCloudWatchRule;
14
+ exports.ensureInlinePolicyAttached = ensureInlinePolicyAttached;
15
+ exports.ensureInstanceProfileExists = ensureInstanceProfileExists;
16
+ exports.ensurePoliciesAttached = ensurePoliciesAttached;
17
+ exports.ensureRoleAdded = ensureRoleAdded;
18
+ exports.ensureRoleExists = ensureRoleExists;
25
19
  exports.ensureRuleTargetExists = ensureRuleTargetExists;
26
- exports.coloredStatusText = coloredStatusText;
27
- exports.createVersionDescription = createVersionDescription;
28
20
  exports.ensureSsmDocument = ensureSsmDocument;
29
- exports.pickInstance = pickInstance;
30
- exports.connectToInstance = connectToInstance;
31
21
  exports.executeSSHCommand = executeSSHCommand;
32
-
22
+ exports.findBucketWithPrefix = findBucketWithPrefix;
23
+ exports.getAccountId = getAccountId;
24
+ exports.getLogs = getLogs;
25
+ exports.getNodeVersion = getNodeVersion;
26
+ exports.logStep = logStep;
27
+ exports.names = names;
28
+ exports.pickInstance = pickInstance;
29
+ exports.selectPlatformArn = selectPlatformArn;
30
+ exports.shouldRebuild = shouldRebuild;
31
+ exports.tmpBuildPath = tmpBuildPath;
33
32
  var _axios = _interopRequireDefault(require("axios"));
34
-
35
33
  var _chalk = _interopRequireDefault(require("chalk"));
36
-
37
34
  var _fs = _interopRequireDefault(require("fs"));
38
-
39
35
  var _lodash = require("lodash");
40
-
41
36
  var _os = _interopRequireDefault(require("os"));
42
-
43
37
  var _randomSeed = _interopRequireDefault(require("random-seed"));
44
-
45
38
  var _uuid = _interopRequireDefault(require("uuid"));
46
-
47
39
  var _child_process = require("child_process");
48
-
49
40
  var _aws = require("./aws");
50
-
51
41
  var _recheck = require("./recheck");
52
-
53
42
  var _envReady = require("./env-ready");
54
-
55
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
56
-
57
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
58
-
59
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
60
-
61
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
43
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
44
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
45
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
46
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
47
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
48
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
49
+ const pkg = require('../package.json'); // Adjust the path as needed
62
50
 
63
51
  function logStep(message) {
64
- console.log(_chalk.default.blue(message));
52
+ console.log(`v${pkg?.version} ${_chalk.default.blue(message)}`);
65
53
  }
66
-
67
54
  function shouldRebuild(bundlePath, useCachedBuild) {
68
55
  if (_fs.default.existsSync(bundlePath) && useCachedBuild) {
69
56
  return false;
70
57
  }
71
-
72
58
  return true;
73
59
  }
74
-
75
60
  function tmpBuildPath(appPath, api) {
76
61
  const rand = _randomSeed.default.create(appPath);
77
-
78
62
  const uuidNumbers = [];
79
-
80
63
  for (let i = 0; i < 16; i++) {
81
64
  uuidNumbers.push(rand(255));
82
65
  }
83
-
84
66
  return api.resolvePath(_os.default.tmpdir(), `mup-meteor-${_uuid.default.v4({
85
67
  random: uuidNumbers
86
68
  })}`);
87
69
  }
88
-
89
70
  function names(config) {
90
71
  const name = config.app.name.toLowerCase();
91
72
  return {
@@ -104,12 +85,10 @@ function names(config) {
104
85
  automationDocument: 'mup-graceful-shutdown'
105
86
  };
106
87
  }
107
-
108
88
  function createUniqueName(prefix = '') {
109
89
  const randomNumbers = Math.floor(Math.random() * 10000);
110
90
  return `${prefix}-${Date.now()}-${randomNumbers}`;
111
91
  }
112
-
113
92
  async function retrieveEnvironmentInfo(api, count) {
114
93
  const config = api.getConfig();
115
94
  const {
@@ -121,13 +100,11 @@ async function retrieveEnvironmentInfo(api, count) {
121
100
  EnvironmentName: environment,
122
101
  InfoType: 'tail'
123
102
  }).promise();
124
-
125
103
  if (EnvironmentInfo.length > 0) {
126
104
  return EnvironmentInfo;
127
105
  } else if (count > 5) {
128
106
  throw new Error('No logs');
129
107
  }
130
-
131
108
  return new Promise((resolve, reject) => {
132
109
  setTimeout(() => {
133
110
  // The logs aren't always available, so retry until they are
@@ -136,7 +113,6 @@ async function retrieveEnvironmentInfo(api, count) {
136
113
  }, (0, _recheck.getRecheckInterval)());
137
114
  });
138
115
  }
139
-
140
116
  async function getLogs(api, logNames) {
141
117
  const config = api.getConfig();
142
118
  const {
@@ -160,11 +136,9 @@ async function getLogs(api, logNames) {
160
136
  }) => {
161
137
  // The separator changed with Amazon Linux 2
162
138
  let parts = data.split('----------------------------------------\n/var/log/');
163
-
164
139
  if (parts.length === 1) {
165
140
  parts = data.split('-------------------------------------\n/var/log/');
166
141
  }
167
-
168
142
  data = logNames.map(name => parts.find(part => part.trim().startsWith(name)));
169
143
  resolve({
170
144
  data,
@@ -173,36 +147,28 @@ async function getLogs(api, logNames) {
173
147
  }).catch(reject);
174
148
  })));
175
149
  }
176
-
177
150
  function getNodeVersion(api, bundlePath) {
178
151
  let star = _fs.default.readFileSync(api.resolvePath(bundlePath, 'bundle/star.json')).toString();
179
-
180
152
  const nodeVersionTxt = _fs.default.readFileSync(api.resolvePath(bundlePath, 'bundle/.node_version.txt')).toString();
181
-
182
153
  star = JSON.parse(star);
183
-
184
154
  if (star.npmVersion) {
185
155
  return {
186
156
  nodeVersion: star.nodeVersion,
187
157
  npmVersion: star.npmVersion
188
158
  };
189
159
  }
190
-
191
160
  const nodeVersion = nodeVersionTxt.substr(1);
192
-
193
161
  if (nodeVersion.startsWith('4')) {
194
162
  return {
195
163
  nodeVersion,
196
164
  npmVersion: '4.6.1'
197
165
  };
198
166
  }
199
-
200
167
  return {
201
168
  nodeVersion,
202
169
  npmVersion: '3.10.5'
203
170
  };
204
171
  }
205
-
206
172
  async function selectPlatformArn(awsPlatformBranchName) {
207
173
  console.log('----> Amazon BranchName:', awsPlatformBranchName);
208
174
  const {
@@ -222,11 +188,9 @@ async function selectPlatformArn(awsPlatformBranchName) {
222
188
  Values: [awsPlatformBranchName]
223
189
  }]
224
190
  }).promise();
225
-
226
191
  if (PlatformBranchSummaryList.length === 0) {
227
192
  throw new Error('Unable to find supported Node.js platform');
228
193
  }
229
-
230
194
  const branchName = PlatformBranchSummaryList[0].BranchName;
231
195
  console.log('----> Amazon Platform:', branchName);
232
196
  const {
@@ -246,7 +210,6 @@ async function selectPlatformArn(awsPlatformBranchName) {
246
210
  console.log('----> Amazon ARN:', arn);
247
211
  return arn;
248
212
  }
249
-
250
213
  async function attachPolicies(config, roleName, policies) {
251
214
  const promises = [];
252
215
  policies.forEach(policy => {
@@ -254,39 +217,33 @@ async function attachPolicies(config, roleName, policies) {
254
217
  RoleName: roleName,
255
218
  PolicyArn: policy
256
219
  }).promise();
257
-
258
220
  promises.push(promise);
259
221
  });
260
222
  await Promise.all(promises);
261
223
  }
262
-
263
224
  function getAccountId() {
264
225
  return _aws.sts.getCallerIdentity().promise().then(({
265
226
  Account
266
227
  }) => Account);
267
228
  }
268
-
269
229
  async function ensureRoleExists(name, assumeRolePolicyDocument, ensureAssumeRolePolicy) {
270
230
  let exists = true;
271
231
  let updateAssumeRolePolicy = false;
272
-
273
232
  try {
274
233
  const {
275
234
  Role
276
235
  } = await _aws.iam.getRole({
277
236
  RoleName: name
278
237
  }).promise();
279
- const currentAssumeRolePolicy = decodeURIComponent(Role.AssumeRolePolicyDocument); // Make the whitespace consistent with the current document
280
-
238
+ const currentAssumeRolePolicy = decodeURIComponent(Role.AssumeRolePolicyDocument);
239
+ // Make the whitespace consistent with the current document
281
240
  assumeRolePolicyDocument = JSON.stringify(JSON.parse(assumeRolePolicyDocument));
282
-
283
241
  if (currentAssumeRolePolicy !== assumeRolePolicyDocument && ensureAssumeRolePolicy) {
284
242
  updateAssumeRolePolicy = true;
285
243
  }
286
244
  } catch (e) {
287
245
  exists = false;
288
246
  }
289
-
290
247
  if (!exists) {
291
248
  await _aws.iam.createRole({
292
249
  RoleName: name,
@@ -299,10 +256,8 @@ async function ensureRoleExists(name, assumeRolePolicyDocument, ensureAssumeRole
299
256
  }).promise();
300
257
  }
301
258
  }
302
-
303
259
  async function ensureInstanceProfileExists(config, name) {
304
260
  let exists = true;
305
-
306
261
  try {
307
262
  await _aws.iam.getInstanceProfile({
308
263
  InstanceProfileName: name
@@ -310,14 +265,12 @@ async function ensureInstanceProfileExists(config, name) {
310
265
  } catch (e) {
311
266
  exists = false;
312
267
  }
313
-
314
268
  if (!exists) {
315
269
  await _aws.iam.createInstanceProfile({
316
270
  InstanceProfileName: name
317
271
  }).promise();
318
272
  }
319
273
  }
320
-
321
274
  async function ensureRoleAdded(config, instanceProfile, role) {
322
275
  let added = true;
323
276
  const {
@@ -325,11 +278,9 @@ async function ensureRoleAdded(config, instanceProfile, role) {
325
278
  } = await _aws.iam.getInstanceProfile({
326
279
  InstanceProfileName: instanceProfile
327
280
  }).promise();
328
-
329
281
  if (InstanceProfile.Roles.length === 0 || InstanceProfile.Roles[0].RoleName !== role) {
330
282
  added = false;
331
283
  }
332
-
333
284
  if (!added) {
334
285
  await _aws.iam.addRoleToInstanceProfile({
335
286
  InstanceProfileName: instanceProfile,
@@ -337,7 +288,6 @@ async function ensureRoleAdded(config, instanceProfile, role) {
337
288
  }).promise();
338
289
  }
339
290
  }
340
-
341
291
  async function ensurePoliciesAttached(config, role, policies) {
342
292
  let {
343
293
  AttachedPolicies
@@ -349,33 +299,27 @@ async function ensurePoliciesAttached(config, role, policies) {
349
299
  if (AttachedPolicies.indexOf(policy) === -1) {
350
300
  result.push(policy);
351
301
  }
352
-
353
302
  return result;
354
303
  }, []);
355
-
356
304
  if (unattachedPolicies.length > 0) {
357
305
  await attachPolicies(config, role, unattachedPolicies);
358
306
  }
359
307
  }
360
-
361
308
  async function ensureInlinePolicyAttached(role, policyName, policyDocument) {
362
309
  let exists = true;
363
310
  let needsUpdating = false;
364
-
365
311
  try {
366
312
  const result = await _aws.iam.getRolePolicy({
367
313
  RoleName: role,
368
314
  PolicyName: policyName
369
315
  }).promise();
370
316
  const currentPolicyDocument = decodeURIComponent(result.PolicyDocument);
371
-
372
317
  if (currentPolicyDocument !== policyDocument) {
373
318
  needsUpdating = true;
374
319
  }
375
320
  } catch (e) {
376
321
  exists = false;
377
322
  }
378
-
379
323
  if (!exists || needsUpdating) {
380
324
  await _aws.iam.putRolePolicy({
381
325
  RoleName: role,
@@ -384,7 +328,6 @@ async function ensureInlinePolicyAttached(role, policyName, policyDocument) {
384
328
  }).promise();
385
329
  }
386
330
  }
387
-
388
331
  async function ensureBucketExists(buckets, bucketName, region) {
389
332
  if (!buckets.find(bucket => bucket.Name === bucketName)) {
390
333
  await _aws.s3.createBucket(_objectSpread({
@@ -397,15 +340,12 @@ async function ensureBucketExists(buckets, bucketName, region) {
397
340
  return true;
398
341
  }
399
342
  }
400
-
401
343
  function findBucketWithPrefix(buckets, prefix) {
402
344
  return buckets.find(bucket => bucket.Name.indexOf(prefix) === 0);
403
345
  }
404
-
405
346
  async function ensureBucketPolicyAttached(bucketName, policy) {
406
347
  let error = false;
407
348
  let currentPolicy;
408
-
409
349
  try {
410
350
  const {
411
351
  Policy
@@ -416,7 +356,6 @@ async function ensureBucketPolicyAttached(bucketName, policy) {
416
356
  } catch (e) {
417
357
  error = true;
418
358
  }
419
-
420
359
  if (error || currentPolicy !== policy) {
421
360
  const params = {
422
361
  Bucket: bucketName,
@@ -425,10 +364,8 @@ async function ensureBucketPolicyAttached(bucketName, policy) {
425
364
  await _aws.s3.putBucketPolicy(params).promise();
426
365
  }
427
366
  }
428
-
429
367
  async function ensureCloudWatchRule(name, description, eventPattern) {
430
368
  let error = false;
431
-
432
369
  try {
433
370
  await _aws.cloudWatchEvents.describeRule({
434
371
  Name: name
@@ -436,7 +373,6 @@ async function ensureCloudWatchRule(name, description, eventPattern) {
436
373
  } catch (e) {
437
374
  error = true;
438
375
  }
439
-
440
376
  if (error) {
441
377
  await _aws.cloudWatchEvents.putRule({
442
378
  Name: name,
@@ -445,17 +381,14 @@ async function ensureCloudWatchRule(name, description, eventPattern) {
445
381
  }).promise();
446
382
  return true;
447
383
  }
448
-
449
384
  return false;
450
385
  }
451
-
452
386
  async function ensureRuleTargetExists(ruleName, target) {
453
387
  const {
454
388
  Targets
455
389
  } = await _aws.cloudWatchEvents.listTargetsByRule({
456
390
  Rule: ruleName
457
391
  }).promise();
458
-
459
392
  if (!Targets.find(_target => (0, _lodash.isEqual)(_target, target))) {
460
393
  const params = {
461
394
  Rule: ruleName,
@@ -465,7 +398,6 @@ async function ensureRuleTargetExists(ruleName, target) {
465
398
  return true;
466
399
  }
467
400
  }
468
-
469
401
  function coloredStatusText(envColor, text) {
470
402
  if (envColor === 'Green') {
471
403
  return _chalk.default.green(text);
@@ -474,14 +406,11 @@ function coloredStatusText(envColor, text) {
474
406
  } else if (envColor === 'Red') {
475
407
  return _chalk.default.red(text);
476
408
  }
477
-
478
409
  return text;
479
410
  }
480
-
481
411
  function createVersionDescription(api, appConfig) {
482
412
  const appPath = api.resolvePath(api.getBasePath(), appConfig.path);
483
413
  let description = '';
484
-
485
414
  try {
486
415
  description = (0, _child_process.execSync)('git log -1 --pretty=%B', {
487
416
  cwd: appPath,
@@ -490,30 +419,25 @@ function createVersionDescription(api, appConfig) {
490
419
  } catch (e) {
491
420
  description = `Deployed by Mup on ${new Date().toUTCString()}`;
492
421
  }
493
-
494
422
  return description.split('\n')[0].slice(0, 195);
495
423
  }
496
-
497
424
  async function ensureSsmDocument(name, content) {
498
425
  let exists = true;
499
426
  let needsUpdating = false;
500
-
501
427
  try {
502
428
  const result = await _aws.ssm.getDocument({
503
429
  Name: name,
504
430
  DocumentVersion: '$DEFAULT'
505
- }).promise(); // If the document was created or edited on the AWS console, there is extra new
431
+ }).promise();
432
+ // If the document was created or edited on the AWS console, there is extra new
506
433
  // line characters and whitespace
507
-
508
434
  const currentContent = JSON.stringify(JSON.parse(result.Content.replace(/\r?\n|\r/g, '')));
509
-
510
435
  if (currentContent !== content) {
511
436
  needsUpdating = true;
512
437
  }
513
438
  } catch (e) {
514
439
  exists = false;
515
440
  }
516
-
517
441
  if (!exists) {
518
442
  await _aws.ssm.createDocument({
519
443
  Content: content,
@@ -536,7 +460,6 @@ async function ensureSsmDocument(name, content) {
536
460
  throw e;
537
461
  }
538
462
  }
539
-
540
463
  const result = await _aws.ssm.getDocument({
541
464
  Name: name,
542
465
  DocumentVersion: '$LATEST'
@@ -547,7 +470,6 @@ async function ensureSsmDocument(name, content) {
547
470
  }).promise();
548
471
  }
549
472
  }
550
-
551
473
  async function pickInstance(config, instance) {
552
474
  const {
553
475
  environment
@@ -566,18 +488,15 @@ async function pickInstance(config, instance) {
566
488
  description
567
489
  };
568
490
  }
569
-
570
491
  async function connectToInstance(api, instanceId, commandLabel) {
571
492
  const {
572
493
  sshKey
573
494
  } = api.getConfig().app;
574
-
575
495
  if (!sshKey) {
576
496
  const error = new Error('missing sshKey config');
577
497
  error.solution = 'Learn how to configure sshKey at https://github.com/zodern/mup-aws-beanstalk/blob/master/docs/index.md#meteor-shell-and-debug';
578
498
  throw error;
579
499
  }
580
-
581
500
  const {
582
501
  Reservations
583
502
  } = await _aws.ec2.describeInstances({
@@ -590,13 +509,10 @@ async function connectToInstance(api, instanceId, commandLabel) {
590
509
  data: ipAddress
591
510
  } = await _axios.default.get('https://ipv4.icanhazip.com');
592
511
  ipAddress = ipAddress.trim();
593
-
594
512
  if (securityGroups.length > 1) {
595
513
  console.warn('Instance has more than one security group. Please open a GitHub issue for mup-aws-beanstalk');
596
514
  }
597
-
598
515
  let ruleIds = [];
599
-
600
516
  try {
601
517
  const {
602
518
  SecurityGroupRules
@@ -614,14 +530,14 @@ async function connectToInstance(api, instanceId, commandLabel) {
614
530
  }).promise();
615
531
  ruleIds = SecurityGroupRules.map(rule => rule.SecurityGroupRuleId);
616
532
  } catch (e) {
617
- if (e.code === 'InvalidPermission.Duplicate') {// This rule already exists
533
+ if (e.code === 'InvalidPermission.Duplicate') {
534
+ // This rule already exists
618
535
  // TODO: should we find the rule id so we can remove it, or leave it in
619
536
  // case the user had manually added this rule?
620
537
  } else {
621
538
  throw e;
622
539
  }
623
540
  }
624
-
625
541
  await _aws.ec2InstanceConnect.sendSSHPublicKey({
626
542
  InstanceId: instanceId,
627
543
  AvailabilityZone: availabilityZone,
@@ -636,22 +552,18 @@ async function connectToInstance(api, instanceId, commandLabel) {
636
552
  };
637
553
  return {
638
554
  sshOptions,
639
-
640
555
  removeSSHAccess() {
641
556
  if (ruleIds.length === 0) {
642
557
  return;
643
558
  }
644
-
645
559
  console.log('Removing temporary security group rule for SSH');
646
560
  return _aws.ec2.revokeSecurityGroupIngress({
647
561
  GroupId: securityGroups[0],
648
562
  SecurityGroupRuleIds: ruleIds
649
563
  }).promise();
650
564
  }
651
-
652
565
  };
653
566
  }
654
-
655
567
  async function executeSSHCommand(conn, command) {
656
568
  return new Promise((resolve, reject) => {
657
569
  conn.exec(command, (err, outputStream) => {
@@ -660,7 +572,6 @@ async function executeSSHCommand(conn, command) {
660
572
  reject(err);
661
573
  return;
662
574
  }
663
-
664
575
  let output = '';
665
576
  outputStream.on('data', data => {
666
577
  output += data;