@devicecloud.dev/dcd 3.6.2 → 3.6.3

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.
@@ -62,6 +62,7 @@ export default class Cloud extends Command {
62
62
  'runner-type': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
63
63
  report: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
64
64
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
65
+ 'json-file': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
65
66
  };
66
67
  static enableJsonFlag: boolean;
67
68
  private versionCheck;
@@ -6,6 +6,7 @@ const core_1 = require("@oclif/core");
6
6
  const cli_ux_1 = require("@oclif/core/lib/cli-ux");
7
7
  const errors_1 = require("@oclif/core/lib/errors");
8
8
  const path = require("node:path");
9
+ const fs = require("node:fs");
9
10
  const constants_1 = require("../constants");
10
11
  const methods_1 = require("../methods");
11
12
  const plan_1 = require("../plan");
@@ -46,6 +47,10 @@ process.on('warning', (warning) => {
46
47
  return;
47
48
  }
48
49
  });
50
+ const escapeShellValue = (value) => {
51
+ // Escape special characters that could cause shell interpretation issues
52
+ return value.replace(/(["\\'$`!\s\[\]{}()&|;<>*?#^~])/g, '\\$1');
53
+ };
49
54
  class Cloud extends core_1.Command {
50
55
  static args = {
51
56
  firstFile: core_1.Args.string({
@@ -80,8 +85,27 @@ class Cloud extends core_1.Command {
80
85
  let output = null;
81
86
  try {
82
87
  const { args, flags, raw } = await this.parse(Cloud);
88
+ // Log the full command that was run
89
+ const commandParts = ['dcd cloud'];
90
+ if (args.firstFile)
91
+ commandParts.push(escapeShellValue(args.firstFile));
92
+ if (args.secondFile)
93
+ commandParts.push(escapeShellValue(args.secondFile));
94
+ for (const [key, value] of Object.entries(flags)) {
95
+ if (value && value.toString().length > 0) {
96
+ if (typeof value === 'boolean') {
97
+ commandParts.push(`--${key}`);
98
+ }
99
+ else if (Array.isArray(value)) {
100
+ commandParts.push(`--${key}=${value.map((v) => escapeShellValue(v)).join(',')}`);
101
+ }
102
+ else {
103
+ commandParts.push(`--${key}=${escapeShellValue(value.toString())}`);
104
+ }
105
+ }
106
+ }
107
+ this.log(`\nCommand ran: ${commandParts.join(' ')}\n`);
83
108
  let { 'additional-app-binary-ids': nonFlatAdditionalAppBinaryIds, 'additional-app-files': nonFlatAdditionalAppFiles, 'android-api-level': androidApiLevel, 'android-device': androidDevice, apiKey: apiKeyFlag, apiUrl, 'app-binary-id': appBinaryId, 'app-file': appFile, 'artifacts-path': artifactsPath, async, config: configFile, 'device-locale': deviceLocale, 'download-artifacts': downloadArtifacts, env, 'exclude-flows': excludeFlows, 'exclude-tags': excludeTags, flows, 'google-play': googlePlay, 'include-tags': includeTags, 'ignore-sha-check': ignoreShaCheck, 'ios-device': iOSDevice, 'ios-version': iOSVersion, 'maestro-version': maestroVersion, name, orientation, quiet, retry, report, 'runner-type': runnerType, 'x86-arch': x86Arch, json, ...rest } = flags;
84
- // If in JSON mode, temporarily intercept stdout to suppress the warning
85
109
  if (json) {
86
110
  const originalStdoutWrite = process.stdout.write;
87
111
  process.stdout.write = function (chunk, encodingOrCallback, cb) {
@@ -327,16 +351,24 @@ class Cloud extends core_1.Command {
327
351
  this.log(`Your upload ID is: ${results[0].test_upload_id}`);
328
352
  this.log(`Poll upload status using: dcd status --api-key ... --upload-id ${results[0].test_upload_id}`);
329
353
  if (async) {
354
+ const jsonOutput = {
355
+ uploadId: results[0].test_upload_id,
356
+ consoleUrl: url,
357
+ status: 'PENDING',
358
+ tests: results.map((r) => ({
359
+ name: r.test_file_name,
360
+ status: r.status,
361
+ })),
362
+ };
363
+ if (flags['json-file']) {
364
+ const jsonFilePath = name
365
+ ? `${name}_dcd.json`
366
+ : `${results[0].test_upload_id}_dcd.json`;
367
+ fs.writeFileSync(jsonFilePath, JSON.stringify(jsonOutput, null, 2));
368
+ this.log(`JSON output written to: ${path.resolve(jsonFilePath)}`);
369
+ }
330
370
  if (json) {
331
- return {
332
- uploadId: results[0].test_upload_id,
333
- consoleUrl: url,
334
- status: 'PENDING',
335
- tests: results.map((r) => ({
336
- name: r.test_file_name,
337
- status: r.status,
338
- })),
339
- };
371
+ return jsonOutput;
340
372
  }
341
373
  this.log('Not waiting for results as async flag is set to true');
342
374
  return;
@@ -403,30 +435,46 @@ class Cloud extends core_1.Command {
403
435
  return result.id === Math.max(...tries.map((t) => t.id));
404
436
  });
405
437
  if (resultsWithoutEarlierTries.some((result) => result.status === 'FAILED')) {
438
+ const jsonOutput = {
439
+ uploadId: results[0].test_upload_id,
440
+ consoleUrl: url,
441
+ status: 'FAILED',
442
+ tests: resultsWithoutEarlierTries.map((r) => ({
443
+ name: r.test_file_name,
444
+ status: r.status,
445
+ })),
446
+ };
447
+ if (flags['json-file']) {
448
+ const jsonFilePath = name
449
+ ? `${name}_dcd.json`
450
+ : `${results[0].test_upload_id}_dcd.json`;
451
+ fs.writeFileSync(jsonFilePath, JSON.stringify(jsonOutput, null, 2));
452
+ this.log(`JSON output written to: ${path.resolve(jsonFilePath)}`);
453
+ }
406
454
  if (json) {
407
- output = {
408
- uploadId: results[0].test_upload_id,
409
- consoleUrl: url,
410
- status: 'FAILED',
411
- tests: resultsWithoutEarlierTries.map((r) => ({
412
- name: r.test_file_name,
413
- status: r.status,
414
- })),
415
- };
455
+ output = jsonOutput;
416
456
  }
417
457
  reject(new Error('RUN_FAILED'));
418
458
  }
419
459
  else {
460
+ const jsonOutput = {
461
+ uploadId: results[0].test_upload_id,
462
+ consoleUrl: url,
463
+ status: 'PASSED',
464
+ tests: resultsWithoutEarlierTries.map((r) => ({
465
+ name: r.test_file_name,
466
+ status: r.status,
467
+ })),
468
+ };
469
+ if (flags['json-file']) {
470
+ const jsonFilePath = name
471
+ ? `${name}_dcd.json`
472
+ : `${results[0].test_upload_id}_dcd.json`;
473
+ fs.writeFileSync(jsonFilePath, JSON.stringify(jsonOutput, null, 2));
474
+ this.log(`JSON output written to: ${path.resolve(jsonFilePath)}`);
475
+ }
420
476
  if (json) {
421
- output = {
422
- uploadId: results[0].test_upload_id,
423
- consoleUrl: url,
424
- status: 'PASSED',
425
- tests: resultsWithoutEarlierTries.map((r) => ({
426
- name: r.test_file_name,
427
- status: r.status,
428
- })),
429
- };
477
+ output = jsonOutput;
430
478
  }
431
479
  }
432
480
  sequentialPollFaillures = 0;
@@ -32,6 +32,7 @@ export declare const flags: {
32
32
  'runner-type': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
33
33
  report: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
34
34
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
35
+ 'json-file': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
35
36
  };
36
37
  export declare const iOSCompatibilityLookup: {
37
38
  [k in EiOSDevices]: string[];
package/dist/constants.js CHANGED
@@ -185,6 +185,10 @@ exports.flags = {
185
185
  json: core_1.Flags.boolean({
186
186
  description: 'Output results in JSON format - note: will always provide exit code 0',
187
187
  }),
188
+ 'json-file': core_1.Flags.boolean({
189
+ description: 'Write JSON output to a file with name <run_name>_dcd.json or <upload_id>_dcd.json if no name is provided',
190
+ required: false,
191
+ }),
188
192
  };
189
193
  exports.iOSCompatibilityLookup = {
190
194
  'ipad-pro-6th-gen': ['16', '17', '18'],
@@ -348,6 +348,13 @@
348
348
  "html"
349
349
  ],
350
350
  "type": "option"
351
+ },
352
+ "json-file": {
353
+ "description": "Write JSON output to a file with name <run_name>_dcd.json or <upload_id>_dcd.json if no name is provided",
354
+ "name": "json-file",
355
+ "required": false,
356
+ "allowNo": false,
357
+ "type": "boolean"
351
358
  }
352
359
  },
353
360
  "hasDynamicHelp": false,
@@ -507,5 +514,5 @@
507
514
  ]
508
515
  }
509
516
  },
510
- "version": "3.6.2"
517
+ "version": "3.6.3"
511
518
  }
package/package.json CHANGED
@@ -79,7 +79,7 @@
79
79
  "prepare": "yarn build",
80
80
  "version": "oclif readme && git add README.md"
81
81
  },
82
- "version": "3.6.2",
82
+ "version": "3.6.3",
83
83
  "bugs": {
84
84
  "url": "https://discord.gg/gm3mJwcNw8"
85
85
  },