@devicecloud.dev/dcd 3.7.11 → 4.0.0

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.
@@ -2,16 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const constants_1 = require("../constants");
5
- const ApiGateway_1 = require("../gateways/ApiGateway");
5
+ const api_gateway_1 = require("../gateways/api-gateway");
6
6
  const methods_1 = require("../methods");
7
7
  class Status extends core_1.Command {
8
8
  static description = 'Get the status of an upload by name or upload ID';
9
+ static enableJsonFlag = true;
9
10
  static examples = [
10
11
  '<%= config.bin %> <%= command.id %> --name my-upload-name',
11
12
  '<%= config.bin %> <%= command.id %> --upload-id 123e4567-e89b-12d3-a456-426614174000 --json',
12
13
  ];
13
- static enableJsonFlag = true;
14
14
  static flags = {
15
+ apiKey: constants_1.flags.apiKey,
16
+ apiUrl: constants_1.flags.apiUrl,
15
17
  json: core_1.Flags.boolean({
16
18
  description: 'output in json format',
17
19
  }),
@@ -23,29 +25,18 @@ class Status extends core_1.Command {
23
25
  description: 'UUID of the upload to check status for',
24
26
  exclusive: ['name'],
25
27
  }),
26
- apiKey: constants_1.flags.apiKey,
27
- apiUrl: constants_1.flags.apiUrl,
28
28
  };
29
- getStatusSymbol(status) {
30
- switch (status) {
31
- case 'PASSED':
32
- return '✓';
33
- case 'FAILED':
34
- return '✗';
35
- case 'CANCELLED':
36
- return '⊘';
37
- case 'PENDING':
38
- return '⋯';
39
- default:
40
- return '?';
41
- }
42
- }
29
+ // eslint-disable-next-line complexity
43
30
  async run() {
44
31
  const { flags } = await this.parse(Status);
45
- const { apiUrl, apiKey: apiKeyFlag, name, 'upload-id': uploadId, json, } = flags;
32
+ const { apiKey: apiKeyFlag, apiUrl, json, name, 'upload-id': uploadId, } = flags;
46
33
  const apiKey = apiKeyFlag || process.env.DEVICE_CLOUD_API_KEY;
47
34
  if (!apiKey) {
48
- this.error('API Key is required. Please provide it via --api-key flag or DEVICE_CLOUD_API_KEY environment variable.');
35
+ this.error('API key is required. Please provide it via --api-key flag or DEVICE_CLOUD_API_KEY environment variable.');
36
+ return;
37
+ }
38
+ if (name && uploadId) {
39
+ this.error('Cannot provide both --name and --upload-id. These options are mutually exclusive.');
49
40
  return;
50
41
  }
51
42
  if (!name && !uploadId) {
@@ -56,7 +47,7 @@ class Status extends core_1.Command {
56
47
  let status = null;
57
48
  for (let attempt = 1; attempt <= 5; attempt++) {
58
49
  try {
59
- status = (await ApiGateway_1.ApiGateway.getUploadStatus(apiUrl, apiKey, {
50
+ status = (await api_gateway_1.ApiGateway.getUploadStatus(apiUrl, apiKey, {
60
51
  name,
61
52
  uploadId,
62
53
  }));
@@ -66,7 +57,9 @@ class Status extends core_1.Command {
66
57
  lastError = error;
67
58
  if (attempt < 5) {
68
59
  this.log(`Network error on attempt ${attempt}/5. Retrying...`);
69
- await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
60
+ await new Promise((resolve) => {
61
+ setTimeout(resolve, 1000 * attempt);
62
+ });
70
63
  }
71
64
  }
72
65
  }
@@ -74,51 +67,47 @@ class Status extends core_1.Command {
74
67
  const errorMessage = `Failed to get status after 5 attempts. Check your network. Last error: ${lastError?.message || 'Unknown error'}`;
75
68
  if (json) {
76
69
  return {
70
+ attempts: 5,
71
+ error: errorMessage,
77
72
  status: 'FAILED',
78
73
  tests: [],
79
- error: errorMessage,
80
- attempts: 5,
81
74
  };
82
75
  }
83
- else {
84
- this.error(errorMessage);
85
- return;
86
- }
76
+ this.error(errorMessage);
77
+ return;
87
78
  }
88
79
  try {
89
80
  if (json) {
90
81
  return status;
91
82
  }
92
- else {
93
- this.log('\n📊 Upload Status');
94
- this.log('═'.repeat(80));
95
- // Display overall status
96
- const overallSymbol = this.getStatusSymbol(status.status);
97
- this.log(`${overallSymbol} Status: ${status.status}`);
98
- if (status.uploadId) {
99
- this.log(`🆔 Upload ID: ${status.uploadId}`);
100
- }
101
- if (status.appBinaryId) {
102
- this.log(`📱 Binary ID: ${status.appBinaryId}`);
103
- }
104
- if (status.consoleUrl) {
105
- this.log(`🔗 Console: ${status.consoleUrl}`);
106
- }
107
- if (status.tests.length > 0) {
108
- this.log('\n📋 Test Results');
109
- this.log('─'.repeat(80));
110
- status.tests.forEach((item) => {
111
- const symbol = this.getStatusSymbol(item.status);
112
- this.log(`${symbol} ${item.name}`);
113
- this.log(` Status: ${item.status}`);
114
- if (item.status === 'FAILED' && item.failReason) {
115
- this.log(` Fail reason: ${item.failReason}`);
116
- }
117
- if (item.durationSeconds) {
118
- this.log(` Duration: ${(0, methods_1.formatDurationSeconds)(item.durationSeconds)}`);
119
- }
120
- this.log('');
121
- });
83
+ this.log('\n📊 Upload Status');
84
+ this.log(''.repeat(80));
85
+ // Display overall status
86
+ const overallSymbol = this.getStatusSymbol(status.status);
87
+ this.log(`${overallSymbol} Status: ${status.status}`);
88
+ if (status.uploadId) {
89
+ this.log(`🆔 Upload ID: ${status.uploadId}`);
90
+ }
91
+ if (status.appBinaryId) {
92
+ this.log(`📱 Binary ID: ${status.appBinaryId}`);
93
+ }
94
+ if (status.consoleUrl) {
95
+ this.log(`🔗 Console: ${status.consoleUrl}`);
96
+ }
97
+ if (status.tests.length > 0) {
98
+ this.log('\n📋 Test Results');
99
+ this.log(''.repeat(80));
100
+ for (const item of status.tests) {
101
+ const symbol = this.getStatusSymbol(item.status);
102
+ this.log(`${symbol} ${item.name}`);
103
+ this.log(` Status: ${item.status}`);
104
+ if (item.status === 'FAILED' && item.failReason) {
105
+ this.log(` Fail reason: ${item.failReason}`);
106
+ }
107
+ if (item.durationSeconds) {
108
+ this.log(` Duration: ${(0, methods_1.formatDurationSeconds)(item.durationSeconds)}`);
109
+ }
110
+ this.log('');
122
111
  }
123
112
  }
124
113
  }
@@ -126,5 +115,24 @@ class Status extends core_1.Command {
126
115
  this.error(`Failed to get status: ${error.message}`);
127
116
  }
128
117
  }
118
+ getStatusSymbol(status) {
119
+ switch (status) {
120
+ case 'PASSED': {
121
+ return '✓';
122
+ }
123
+ case 'FAILED': {
124
+ return '✗';
125
+ }
126
+ case 'CANCELLED': {
127
+ return '⊘';
128
+ }
129
+ case 'PENDING': {
130
+ return '⋯';
131
+ }
132
+ default: {
133
+ return '?';
134
+ }
135
+ }
136
+ }
129
137
  }
130
138
  exports.default = Status;
@@ -4,14 +4,14 @@ export default class Upload extends Command {
4
4
  appFile: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
5
  };
6
6
  static description: string;
7
+ static enableJsonFlag: boolean;
7
8
  static examples: string[];
8
9
  static flags: {
9
- apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
11
  apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
12
  'ignore-sha-check': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
13
  };
13
- static enableJsonFlag: boolean;
14
14
  run(): Promise<{
15
15
  appBinaryId: string;
16
- } | undefined>;
16
+ }>;
17
17
  }
@@ -7,11 +7,12 @@ class Upload extends core_1.Command {
7
7
  static args = {
8
8
  appFile: core_1.Args.string({
9
9
  description: 'The binary file to upload (e.g. test.apk for android or test.app/.zip for ios)',
10
- required: true,
11
10
  name: 'App file',
11
+ required: true,
12
12
  }),
13
13
  };
14
14
  static description = 'Upload an app binary to devicecloud.dev';
15
+ static enableJsonFlag = true;
15
16
  static examples = [
16
17
  '<%= config.bin %> <%= command.id %> path/to/app.apk',
17
18
  '<%= config.bin %> <%= command.id %> path/to/app.zip --api-key YOUR_API_KEY',
@@ -21,7 +22,6 @@ class Upload extends core_1.Command {
21
22
  apiUrl: constants_1.flags.apiUrl,
22
23
  'ignore-sha-check': constants_1.flags['ignore-sha-check'],
23
24
  };
24
- static enableJsonFlag = true;
25
25
  async run() {
26
26
  try {
27
27
  const { args, flags } = await this.parse(Upload);
@@ -1,41 +1,47 @@
1
+ export declare const SUPPORTED_MAESTRO_VERSIONS: string[];
2
+ export declare const DEFAULT_MAESTRO_VERSION = "1.41.0";
3
+ export declare const getLatestMaestroVersion: () => string;
4
+ export declare const resolveMaestroVersion: (version?: string) => string;
1
5
  export declare const flags: {
2
6
  'additional-app-binary-ids': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
3
7
  'additional-app-files': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
4
- 'android-api-level': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
5
- 'android-device': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
6
- 'skip-chrome-onboarding': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
- 'show-crosshairs': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
- apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ 'android-api-level': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ 'android-device': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
11
  apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
- 'app-binary-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
- 'app-file': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'app-binary-id': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ 'app-file': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ 'artifacts-path': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
12
15
  async: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
- config: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
- 'device-locale': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
- 'download-artifacts': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
- 'artifacts-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ config: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
17
17
  debug: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
18
- env: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ 'device-locale': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ 'download-artifacts': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ 'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ env: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
19
22
  'exclude-flows': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
20
23
  'exclude-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
21
- flows: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
24
+ flows: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
22
25
  'google-play': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
- 'include-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
24
26
  'ignore-sha-check': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
25
- 'ios-device': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
26
- 'ios-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
27
- 'x86-arch': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
27
+ 'include-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
28
+ 'ios-device': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
29
+ 'ios-version': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
30
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
31
+ 'json-file': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
32
+ 'json-file-name': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
28
33
  'maestro-version': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
29
- mitmHost: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
30
- mitmPath: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
31
- name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
32
- orientation: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
34
+ metadata: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
35
+ mitmHost: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
36
+ mitmPath: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
37
+ 'moropo-v1-api-key': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
38
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
39
+ orientation: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
33
40
  quiet: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
34
- retry: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
41
+ report: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
42
+ retry: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
35
43
  'runner-type': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
36
- report: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
37
- json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
38
- 'json-file': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
39
- 'moropo-v1-api-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
40
- 'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
44
+ 'show-crosshairs': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
45
+ 'skip-chrome-onboarding': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
46
+ 'x86-arch': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
41
47
  };
package/dist/constants.js CHANGED
@@ -1,8 +1,33 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.flags = void 0;
3
+ exports.flags = exports.resolveMaestroVersion = exports.getLatestMaestroVersion = exports.DEFAULT_MAESTRO_VERSION = exports.SUPPORTED_MAESTRO_VERSIONS = void 0;
4
4
  const core_1 = require("@oclif/core");
5
5
  const device_types_1 = require("./types/device.types");
6
+ // Centralized maestro version definitions - single source of truth
7
+ exports.SUPPORTED_MAESTRO_VERSIONS = [
8
+ '1.39.0',
9
+ '1.39.1',
10
+ '1.39.2',
11
+ '1.39.4',
12
+ '1.39.5',
13
+ '1.39.7',
14
+ '1.39.13',
15
+ '1.40.0',
16
+ '1.40.1',
17
+ '1.40.2',
18
+ '1.40.3',
19
+ '1.41.0',
20
+ ];
21
+ exports.DEFAULT_MAESTRO_VERSION = '1.41.0';
22
+ const getLatestMaestroVersion = () => exports.SUPPORTED_MAESTRO_VERSIONS.at(-1);
23
+ exports.getLatestMaestroVersion = getLatestMaestroVersion;
24
+ const resolveMaestroVersion = (version) => {
25
+ if (version === 'latest') {
26
+ return (0, exports.getLatestMaestroVersion)();
27
+ }
28
+ return version || exports.DEFAULT_MAESTRO_VERSION;
29
+ };
30
+ exports.resolveMaestroVersion = resolveMaestroVersion;
6
31
  exports.flags = {
7
32
  'additional-app-binary-ids': core_1.Flags.string({
8
33
  default: [],
@@ -26,14 +51,6 @@ exports.flags = {
26
51
  description: '[Android only] Android device to run your flow against',
27
52
  options: Object.values(device_types_1.EAndroidDevices),
28
53
  }),
29
- 'skip-chrome-onboarding': core_1.Flags.boolean({
30
- description: '[Android only] Skip Chrome browser onboarding screens when running tests',
31
- default: false,
32
- }),
33
- 'show-crosshairs': core_1.Flags.boolean({
34
- description: '[Android only] Display crosshairs for screen interactions during test execution',
35
- default: false,
36
- }),
37
54
  apiKey: core_1.Flags.string({
38
55
  aliases: ['api-key'],
39
56
  description: 'API key for devicecloud.dev (find this in the console UI). You can also set the DEVICE_CLOUD_API_KEY environment variable.',
@@ -52,12 +69,20 @@ exports.flags = {
52
69
  aliases: ['app-file'],
53
70
  description: 'App binary to run your flows against',
54
71
  }),
72
+ 'artifacts-path': core_1.Flags.string({
73
+ dependsOn: ['download-artifacts'],
74
+ description: 'Custom file path for downloaded artifacts (default: ./artifacts.zip)',
75
+ }),
55
76
  async: core_1.Flags.boolean({
56
77
  description: 'Immediately return (exit code 0) from the command without waiting for the results of the run (useful for saving CI minutes)',
57
78
  }),
58
79
  config: core_1.Flags.file({
59
80
  description: 'Path to custom config.yaml file. If not provided, defaults to config.yaml in root flows folders.',
60
81
  }),
82
+ debug: core_1.Flags.boolean({
83
+ default: false,
84
+ description: 'Enable detailed debug logging for troubleshooting issues',
85
+ }),
61
86
  'device-locale': core_1.Flags.string({
62
87
  description: 'Locale that will be set to a device, ISO-639-1 code and uppercase ISO-3166-1 code e.g. "de_DE" for Germany',
63
88
  }),
@@ -65,13 +90,9 @@ exports.flags = {
65
90
  description: 'Download a zip containing the logs, screenshots and videos for each result in this run. You will debited a $0.01 egress fee for each result. Use --download-artifacts=FAILED for failures only or --download-artifacts=ALL for every result.',
66
91
  options: ['ALL', 'FAILED'],
67
92
  }),
68
- 'artifacts-path': core_1.Flags.string({
69
- description: 'Custom file path for downloaded artifacts (default: ./artifacts.zip)',
70
- dependsOn: ['download-artifacts'],
71
- }),
72
- debug: core_1.Flags.boolean({
73
- description: 'Enable detailed debug logging for troubleshooting issues',
93
+ 'dry-run': core_1.Flags.boolean({
74
94
  default: false,
95
+ description: 'Simulate the run without actually triggering the upload/test, useful for debugging workflow issues.',
75
96
  }),
76
97
  env: core_1.Flags.file({
77
98
  char: 'e',
@@ -102,6 +123,9 @@ exports.flags = {
102
123
  default: false,
103
124
  description: '[Android only] Run your flow against Google Play devices',
104
125
  }),
126
+ 'ignore-sha-check': core_1.Flags.boolean({
127
+ description: 'Ignore the sha hash check and upload the binary regardless of whether it already exists (not recommended)',
128
+ }),
105
129
  'include-tags': core_1.Flags.string({
106
130
  aliases: ['include-tags'],
107
131
  default: [],
@@ -110,9 +134,6 @@ exports.flags = {
110
134
  multipleNonGreedy: true,
111
135
  parse: (input) => input.split(','),
112
136
  }),
113
- 'ignore-sha-check': core_1.Flags.boolean({
114
- description: 'Ignore the sha hash check and upload the binary regardless of whether it already exists (not recommended)',
115
- }),
116
137
  'ios-device': core_1.Flags.string({
117
138
  description: '[iOS only] iOS device to run your flow against',
118
139
  options: Object.values(device_types_1.EiOSDevices),
@@ -121,35 +142,39 @@ exports.flags = {
121
142
  description: '[iOS only] iOS version to run your flow against',
122
143
  options: Object.values(device_types_1.EiOSVersions),
123
144
  }),
124
- 'x86-arch': core_1.Flags.boolean({
125
- description: '[iOS only, experimental] Run your flow against x86 architecture simulator instead of arm64',
126
- default: false,
145
+ json: core_1.Flags.boolean({
146
+ description: 'Output results in JSON format - note: will always provide exit code 0',
147
+ }),
148
+ 'json-file': core_1.Flags.boolean({
149
+ description: 'Write JSON output to a file. File be called <upload_id>_dcd.json unless you supply the --json-file-name flag - note: will always exit with code 0',
150
+ required: false,
151
+ }),
152
+ 'json-file-name': core_1.Flags.string({
153
+ description: 'A custom name for the JSON file (can also include relative path)',
154
+ dependsOn: ['json-file'],
127
155
  }),
128
156
  'maestro-version': core_1.Flags.string({
129
157
  aliases: ['maestroVersion'],
130
- default: '1.39.5',
158
+ default: exports.DEFAULT_MAESTRO_VERSION,
131
159
  description: 'Maestro version to run your flow against',
132
- options: [
133
- '1.39.0',
134
- '1.39.1',
135
- '1.39.2',
136
- '1.39.4',
137
- '1.39.5',
138
- '1.39.7',
139
- '1.39.13',
140
- '1.40.0',
141
- '1.40.1',
142
- '1.40.2',
143
- '1.40.3',
144
- '1.41.0',
145
- ],
160
+ options: [...exports.SUPPORTED_MAESTRO_VERSIONS, 'latest'],
161
+ }),
162
+ metadata: core_1.Flags.string({
163
+ char: 'm',
164
+ description: 'Arbitrary key-value metadata to include with your test run (format: key=value)',
165
+ multiple: true,
166
+ multipleNonGreedy: true,
146
167
  }),
147
168
  mitmHost: core_1.Flags.string({
148
169
  description: 'used for mitmproxy support, enterprise only, contact support if interested',
149
170
  }),
150
171
  mitmPath: core_1.Flags.string({
151
- description: 'used for mitmproxy support, enterprise only, contact support if interested',
152
172
  dependsOn: ['mitmHost'],
173
+ description: 'used for mitmproxy support, enterprise only, contact support if interested',
174
+ }),
175
+ 'moropo-v1-api-key': core_1.Flags.string({
176
+ description: 'API key for Moropo v1 integration',
177
+ required: false,
153
178
  }),
154
179
  name: core_1.Flags.string({
155
180
  description: 'A custom name for your upload (useful for tagging commits etc)',
@@ -163,32 +188,29 @@ exports.flags = {
163
188
  default: false,
164
189
  description: 'Quieter console output that wont provide progress updates',
165
190
  }),
191
+ report: core_1.Flags.string({
192
+ aliases: ['format'],
193
+ description: 'Runs Maestro with the --format flag, this will generate a report in the specified format',
194
+ options: ['junit', 'html'],
195
+ }),
166
196
  retry: core_1.Flags.integer({
167
197
  description: 'Automatically retry the run up to the number of times specified (same as pressing retry in the UI) - this is free of charge',
168
198
  }),
169
199
  'runner-type': core_1.Flags.string({
170
- description: '[experimental] The type of runner to use - note: anything other than default will incur premium pricing tiers, see https://docs.devicecloud.dev/reference/runner-type for more information',
171
200
  default: 'default',
201
+ description: '[experimental] The type of runner to use - note: anything other than default will incur premium pricing tiers, see https://docs.devicecloud.dev/reference/runner-type for more information',
172
202
  options: ['default', 'm4', 'm1'],
173
203
  }),
174
- report: core_1.Flags.string({
175
- aliases: ['format'],
176
- description: 'Runs Maestro with the --format flag, this will generate a report in the specified format',
177
- options: ['junit', 'html'],
178
- }),
179
- json: core_1.Flags.boolean({
180
- description: 'Output results in JSON format - note: will always provide exit code 0',
181
- }),
182
- 'json-file': core_1.Flags.boolean({
183
- description: 'Write JSON output to a file. If you supply the --name flag, file <name>_dcd.json will be written, otherwise file <upload_id>_dcd.json will be written - note: will always exit with code 0',
184
- required: false,
204
+ 'show-crosshairs': core_1.Flags.boolean({
205
+ default: false,
206
+ description: '[Android only] Display crosshairs for screen interactions during test execution',
185
207
  }),
186
- 'moropo-v1-api-key': core_1.Flags.string({
187
- description: 'API key for Moropo v1 integration',
188
- required: false,
208
+ 'skip-chrome-onboarding': core_1.Flags.boolean({
209
+ default: false,
210
+ description: '[Android only] Skip Chrome browser onboarding screens when running tests',
189
211
  }),
190
- 'dry-run': core_1.Flags.boolean({
191
- description: 'Simulate the run without actually triggering the upload/test, useful for debugging workflow issues.',
212
+ 'x86-arch': core_1.Flags.boolean({
192
213
  default: false,
214
+ description: '[iOS only, experimental] Run your flow against x86 architecture simulator instead of arm64',
193
215
  }),
194
216
  };
@@ -0,0 +1,35 @@
1
+ import { TAppMetadata } from '../types';
2
+ export declare const ApiGateway: {
3
+ checkForExistingUpload(baseUrl: string, apiKey: string, sha: string): Promise<{
4
+ appBinaryId: string;
5
+ exists: boolean;
6
+ }>;
7
+ downloadArtifactsZip(baseUrl: string, apiKey: string, uploadId: string, results: "ALL" | "FAILED", artifactsPath?: string): Promise<void>;
8
+ finaliseUpload(baseUrl: string, apiKey: string, id: string, metadata: TAppMetadata, path: string, sha: string): Promise<Record<string, never>>;
9
+ getBinaryUploadUrl(baseUrl: string, apiKey: string, platform: "android" | "ios"): Promise<{
10
+ id: string;
11
+ message: string;
12
+ path: string;
13
+ token: string;
14
+ }>;
15
+ getResultsForUpload(baseUrl: string, apiKey: string, uploadId: string): Promise<{
16
+ results?: import("../types/schema.types").components["schemas"]["TResultResponse"][];
17
+ statusCode?: number;
18
+ }>;
19
+ getUploadStatus(baseUrl: string, apiKey: string, options: {
20
+ name?: string;
21
+ uploadId?: string;
22
+ }): Promise<{
23
+ status: "CANCELLED" | "FAILED" | "PASSED" | "PENDING";
24
+ tests: Array<{
25
+ durationSeconds?: number;
26
+ failReason?: string;
27
+ name: string;
28
+ status: "CANCELLED" | "FAILED" | "PASSED" | "PENDING";
29
+ }>;
30
+ }>;
31
+ uploadFlow(baseUrl: string, apiKey: string, testFormData: FormData): Promise<{
32
+ message?: string;
33
+ results?: import("../types/schema.types").components["schemas"]["IDBResult"][];
34
+ }>;
35
+ };