@devicecloud.dev/dcd 1.0.9 → 1.0.11
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/dist/commands/cloud.d.ts +1 -6
- package/dist/commands/cloud.js +77 -90
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +6 -16
- package/dist/methods.d.ts +6 -1
- package/dist/methods.js +49 -19
- package/oclif.manifest.json +12 -12
- package/package.json +1 -1
package/dist/commands/cloud.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
export declare enum EiOSDevices {
|
|
3
3
|
'ipad-pro-6th-gen' = "ipad-pro-6th-gen",
|
|
4
|
-
'iphone-12' = "iphone-12",
|
|
5
|
-
'iphone-12-mini' = "iphone-12-mini",
|
|
6
|
-
'iphone-12-pro-max' = "iphone-12-pro-max",
|
|
7
4
|
'iphone-13' = "iphone-13",
|
|
8
|
-
'iphone-13-mini' = "iphone-13-mini",
|
|
9
|
-
'iphone-13-pro-max' = "iphone-13-pro-max",
|
|
10
5
|
'iphone-14' = "iphone-14",
|
|
11
6
|
'iphone-14-plus' = "iphone-14-plus",
|
|
12
7
|
'iphone-14-pro' = "iphone-14-pro",
|
|
@@ -37,6 +32,7 @@ export default class Cloud extends Command {
|
|
|
37
32
|
arm64: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
38
33
|
async: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
39
34
|
'device-locale': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
|
+
'download-artifacts': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
40
36
|
env: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
41
37
|
'exclude-flows': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
42
38
|
'exclude-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -45,7 +41,6 @@ export default class Cloud extends Command {
|
|
|
45
41
|
'include-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
46
42
|
'ios-device': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
47
43
|
'ios-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
48
|
-
'legacy-upload': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
49
44
|
'maestro-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
50
45
|
name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
51
46
|
orientation: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
package/dist/commands/cloud.js
CHANGED
|
@@ -20,12 +20,7 @@ const mimeTypeLookupByExtension = {
|
|
|
20
20
|
var EiOSDevices;
|
|
21
21
|
(function (EiOSDevices) {
|
|
22
22
|
EiOSDevices["ipad-pro-6th-gen"] = "ipad-pro-6th-gen";
|
|
23
|
-
EiOSDevices["iphone-12"] = "iphone-12";
|
|
24
|
-
EiOSDevices["iphone-12-mini"] = "iphone-12-mini";
|
|
25
|
-
EiOSDevices["iphone-12-pro-max"] = "iphone-12-pro-max";
|
|
26
23
|
EiOSDevices["iphone-13"] = "iphone-13";
|
|
27
|
-
EiOSDevices["iphone-13-mini"] = "iphone-13-mini";
|
|
28
|
-
EiOSDevices["iphone-13-pro-max"] = "iphone-13-pro-max";
|
|
29
24
|
EiOSDevices["iphone-14"] = "iphone-14";
|
|
30
25
|
EiOSDevices["iphone-14-plus"] = "iphone-14-plus";
|
|
31
26
|
EiOSDevices["iphone-14-pro"] = "iphone-14-pro";
|
|
@@ -63,14 +58,14 @@ class Cloud extends core_1.Command {
|
|
|
63
58
|
}
|
|
64
59
|
await (0, methods_1.versionCheck)(this.config.version);
|
|
65
60
|
const { args, flags, raw } = await this.parse(Cloud);
|
|
66
|
-
const { 'android-api-level': androidApiLevel, 'android-device': androidDevice, apiKey, apiUrl, 'app-binary-id': appBinaryId, 'app-file': appFile, arm64, async, 'device-locale': deviceLocale, env, 'exclude-flows': excludeFlows, 'exclude-tags': excludeTags, flows, 'google-play': googlePlay, 'include-tags': includeTags, 'ios-device': iOSDevice, 'ios-version': iOSVersion, '
|
|
61
|
+
const { 'android-api-level': androidApiLevel, 'android-device': androidDevice, apiKey, apiUrl, 'app-binary-id': appBinaryId, 'app-file': appFile, arm64, async, 'device-locale': deviceLocale, 'download-artifacts': downloadArtifacts, env, 'exclude-flows': excludeFlows, 'exclude-tags': excludeTags, flows, 'google-play': googlePlay, 'include-tags': includeTags, 'ios-device': iOSDevice, 'ios-version': iOSVersion, 'maestro-version': maestroVersion, name, orientation, quiet, ...rest } = flags;
|
|
67
62
|
if (arm64) {
|
|
68
63
|
(0, cli_ux_1.info)('Contact hello@devicecloud.dev to enquire about arm64 devices');
|
|
69
64
|
(0, cli_ux_1.exit)();
|
|
70
65
|
}
|
|
71
66
|
const { firstFile, secondFile } = args;
|
|
72
67
|
let finalBinaryId = appBinaryId;
|
|
73
|
-
|
|
68
|
+
const finalAppFile = appFile ?? firstFile;
|
|
74
69
|
let flowFile = flows ?? secondFile;
|
|
75
70
|
let metadata;
|
|
76
71
|
if (appBinaryId) {
|
|
@@ -136,97 +131,75 @@ class Cloud extends core_1.Command {
|
|
|
136
131
|
`);
|
|
137
132
|
if (!finalBinaryId) {
|
|
138
133
|
core_1.ux.action.start('Uploading binary', 'Initializing', { stdout: true });
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
core_1.ux.action.status = `Uploading`;
|
|
157
|
-
const { binaryId, message } = await (0, methods_1.typeSafePost)(apiUrl, '/uploads/binary', options);
|
|
158
|
-
if (!binaryId)
|
|
159
|
-
throw new Error(message);
|
|
160
|
-
finalBinaryId = binaryId;
|
|
134
|
+
const { id, message, path, token } = await (0, methods_1.typeSafePost)(apiUrl, '/uploads/getBinaryUploadUrl', {
|
|
135
|
+
body: JSON.stringify({
|
|
136
|
+
platform: finalAppFile?.endsWith('.apk') ? 'android' : 'ios',
|
|
137
|
+
}),
|
|
138
|
+
headers: {
|
|
139
|
+
'content-type': 'application/json',
|
|
140
|
+
'x-app-api-key': apiKey,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
finalBinaryId = id;
|
|
144
|
+
if (!path)
|
|
145
|
+
throw new Error(message);
|
|
146
|
+
let file;
|
|
147
|
+
if (finalAppFile?.endsWith('.app')) {
|
|
148
|
+
const zippedAppBlob = await (0, methods_1.compressFolderToBlob)(finalAppFile);
|
|
149
|
+
const filePath = finalAppFile + '.zip';
|
|
150
|
+
file = new file_1.File([zippedAppBlob], filePath);
|
|
161
151
|
}
|
|
162
152
|
else {
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
platform: finalAppFile?.endsWith('.apk') ? 'android' : 'ios',
|
|
166
|
-
}),
|
|
167
|
-
headers: {
|
|
168
|
-
'content-type': 'application/json',
|
|
169
|
-
'x-app-api-key': apiKey,
|
|
170
|
-
},
|
|
153
|
+
const binaryBlob = new Blob([await (0, promises_1.readFile)(finalAppFile)], {
|
|
154
|
+
type: mimeTypeLookupByExtension[finalAppFile.split('.').pop()],
|
|
171
155
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
file = new file_1.File([zippedAppBlob], filePath);
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
const binaryBlob = new Blob([await (0, promises_1.readFile)(finalAppFile)], {
|
|
183
|
-
type: mimeTypeLookupByExtension[finalAppFile.split('.').pop()],
|
|
184
|
-
});
|
|
185
|
-
file = new file_1.File([binaryBlob], finalAppFile);
|
|
186
|
-
}
|
|
187
|
-
try {
|
|
188
|
-
metadata = finalAppFile?.endsWith('.apk')
|
|
189
|
-
? await (0, methods_1.extractAppMetadataAndroid)(finalAppFile)
|
|
156
|
+
file = new file_1.File([binaryBlob], finalAppFile);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
metadata = finalAppFile?.endsWith('.apk')
|
|
160
|
+
? await (0, methods_1.extractAppMetadataAndroid)(finalAppFile)
|
|
161
|
+
: finalAppFile?.endsWith('.zip')
|
|
162
|
+
? await (0, methods_1.extractAppMetadataIosZip)(finalAppFile)
|
|
190
163
|
: await (0, methods_1.extractAppMetadataIos)(finalAppFile);
|
|
191
|
-
}
|
|
192
|
-
catch {
|
|
193
|
-
this.warn('Failed to extact app metadata, please share with support@devicecloud.dev so we can improve our parsing.');
|
|
194
|
-
}
|
|
195
|
-
// this needs to made nicer by using envs or maybe fetching the keys from the getSignedURL call
|
|
196
|
-
const SB = {
|
|
197
|
-
dev: {
|
|
198
|
-
SUPABASE_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImxibXNvd2VodGp3bnFsdXJwZW1iIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDkyMTg0ODcsImV4cCI6MjAyNDc5NDQ4N30.zeLTMAuZ_WwYvGdeP0kdvL_Zrs-RQee5APPyxmWq7qQ',
|
|
199
|
-
SUPABASE_URL: 'https://lbmsowehtjwnqlurpemb.supabase.co',
|
|
200
|
-
},
|
|
201
|
-
prod: {
|
|
202
|
-
SUPABASE_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBneWRucGhiaW1ldGluc2dma2JvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDc1OTQzNDYsImV4cCI6MjAyMzE3MDM0Nn0.hAYOMFxxwX1exkQkY9xyQJGC_GhGnyogkj2N-kBkMI8',
|
|
203
|
-
SUPABASE_URL: 'https://pgydnphbimetinsgfkbo.supabase.co',
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
const { SUPABASE_KEY, SUPABASE_URL } = SB[apiUrl === 'https://api.devicecloud.dev' ? 'prod' : 'dev'];
|
|
207
|
-
const supabase = (0, supabase_js_1.createClient)(SUPABASE_URL, SUPABASE_KEY);
|
|
208
|
-
const uploadToUrl = await supabase.storage
|
|
209
|
-
.from('organizations')
|
|
210
|
-
.uploadToSignedUrl(path, token, file);
|
|
211
|
-
if (uploadToUrl.error)
|
|
212
|
-
throw new Error(uploadToUrl.error);
|
|
213
|
-
const { error } = await (0, methods_1.typeSafePost)(apiUrl, '/uploads/finaliseUpload', {
|
|
214
|
-
body: JSON.stringify({ id, metadata, path }),
|
|
215
|
-
headers: {
|
|
216
|
-
'content-type': 'application/json',
|
|
217
|
-
'x-app-api-key': apiKey,
|
|
218
|
-
},
|
|
219
|
-
});
|
|
220
|
-
if (error)
|
|
221
|
-
throw new Error(error);
|
|
222
164
|
}
|
|
165
|
+
catch {
|
|
166
|
+
this.warn('Failed to extract app metadata, please share with support@devicecloud.dev so we can improve our parsing.');
|
|
167
|
+
}
|
|
168
|
+
// this needs to made nicer by using envs or maybe fetching the keys from the getSignedURL call
|
|
169
|
+
const SB = {
|
|
170
|
+
dev: {
|
|
171
|
+
SUPABASE_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImxibXNvd2VodGp3bnFsdXJwZW1iIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDkyMTg0ODcsImV4cCI6MjAyNDc5NDQ4N30.zeLTMAuZ_WwYvGdeP0kdvL_Zrs-RQee5APPyxmWq7qQ',
|
|
172
|
+
SUPABASE_URL: 'https://lbmsowehtjwnqlurpemb.supabase.co',
|
|
173
|
+
},
|
|
174
|
+
prod: {
|
|
175
|
+
SUPABASE_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBneWRucGhiaW1ldGluc2dma2JvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDc1OTQzNDYsImV4cCI6MjAyMzE3MDM0Nn0.hAYOMFxxwX1exkQkY9xyQJGC_GhGnyogkj2N-kBkMI8',
|
|
176
|
+
SUPABASE_URL: 'https://pgydnphbimetinsgfkbo.supabase.co',
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
const { SUPABASE_KEY, SUPABASE_URL } = SB[apiUrl === 'https://api.devicecloud.dev' ? 'prod' : 'dev'];
|
|
180
|
+
const supabase = (0, supabase_js_1.createClient)(SUPABASE_URL, SUPABASE_KEY);
|
|
181
|
+
const uploadToUrl = await supabase.storage
|
|
182
|
+
.from('organizations')
|
|
183
|
+
.uploadToSignedUrl(path, token, file);
|
|
184
|
+
if (uploadToUrl.error)
|
|
185
|
+
throw new Error(uploadToUrl.error);
|
|
186
|
+
const { error } = await (0, methods_1.typeSafePost)(apiUrl, '/uploads/finaliseUpload', {
|
|
187
|
+
body: JSON.stringify({ id, metadata, path }),
|
|
188
|
+
headers: {
|
|
189
|
+
'content-type': 'application/json',
|
|
190
|
+
'x-app-api-key': apiKey,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
if (error)
|
|
194
|
+
throw new Error(error);
|
|
223
195
|
core_1.ux.action.stop(`\nBinary uploaded with id: ${finalBinaryId}`);
|
|
224
196
|
}
|
|
225
197
|
const testFormData = new FormData();
|
|
226
198
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
227
199
|
const envObject = (env ?? []).reduce((acc, cur) => {
|
|
228
|
-
const [key, value] = cur.split('=');
|
|
229
|
-
|
|
200
|
+
const [key, ...value] = cur.split('=');
|
|
201
|
+
// handle case where value includes an equals sign
|
|
202
|
+
acc[key] = value.join('=');
|
|
230
203
|
return acc;
|
|
231
204
|
}, {});
|
|
232
205
|
const buffer = await (0, methods_1.compressFilesFromRelativePath)(flowFile?.endsWith('.yaml') || flowFile?.endsWith('.yml')
|
|
@@ -267,8 +240,6 @@ class Cloud extends core_1.Command {
|
|
|
267
240
|
testFormData.set('iOSDevice', iOSDevice.toString());
|
|
268
241
|
if (name)
|
|
269
242
|
testFormData.set('name', name.toString());
|
|
270
|
-
if (metadata)
|
|
271
|
-
testFormData.set('metadata', JSON.stringify(metadata));
|
|
272
243
|
for (const [key, value] of Object.entries(rest)) {
|
|
273
244
|
if (value) {
|
|
274
245
|
testFormData.set(key, value);
|
|
@@ -322,6 +293,22 @@ class Cloud extends core_1.Command {
|
|
|
322
293
|
core_1.ux.url(url, url);
|
|
323
294
|
(0, cli_ux_1.info)('\n');
|
|
324
295
|
clearInterval(intervalId);
|
|
296
|
+
if (downloadArtifacts) {
|
|
297
|
+
try {
|
|
298
|
+
await (0, methods_1.typeSafePostDownload)(apiUrl, `/results/${results[0].test_upload_id}/download`, {
|
|
299
|
+
body: JSON.stringify({ results: downloadArtifacts }),
|
|
300
|
+
headers: {
|
|
301
|
+
'content-type': 'application/json',
|
|
302
|
+
'x-app-api-key': apiKey,
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
(0, cli_ux_1.info)('\n');
|
|
306
|
+
(0, cli_ux_1.info)('Test artifacts have been downloaded to ./artifacts.zip');
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
this.warn('Failed to download artifacts');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
325
312
|
if (updatedResults.some((result) => result.status === 'FAILED')) {
|
|
326
313
|
// eslint-disable-next-line no-process-exit, unicorn/no-process-exit
|
|
327
314
|
process.exit(2);
|
package/dist/constants.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare const flags: {
|
|
|
9
9
|
arm64: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
async: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
'device-locale': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
'download-artifacts': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
13
|
env: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
14
|
'exclude-flows': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
15
|
'exclude-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -17,7 +18,6 @@ export declare const flags: {
|
|
|
17
18
|
'include-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
19
|
'ios-device': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
20
|
'ios-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
-
'legacy-upload': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
21
|
'maestro-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
22
|
name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
23
|
orientation: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
package/dist/constants.js
CHANGED
|
@@ -45,6 +45,10 @@ exports.flags = {
|
|
|
45
45
|
'device-locale': core_1.Flags.string({
|
|
46
46
|
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',
|
|
47
47
|
}),
|
|
48
|
+
'download-artifacts': core_1.Flags.string({
|
|
49
|
+
description: 'BETA (API may change) - 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.',
|
|
50
|
+
options: ['ALL', 'FAILED'],
|
|
51
|
+
}),
|
|
48
52
|
env: core_1.Flags.file({
|
|
49
53
|
char: 'e',
|
|
50
54
|
description: 'One or more environment variables to inject into your flows',
|
|
@@ -85,12 +89,7 @@ exports.flags = {
|
|
|
85
89
|
'ios-device': core_1.Flags.string({
|
|
86
90
|
description: '[iOS only] iOS device to run your flow against',
|
|
87
91
|
options: [
|
|
88
|
-
'iphone-12',
|
|
89
|
-
'iphone-12-mini',
|
|
90
|
-
'iphone-12-pro-max',
|
|
91
92
|
'iphone-13',
|
|
92
|
-
'iphone-13-mini',
|
|
93
|
-
'iphone-13-pro-max',
|
|
94
93
|
'iphone-14',
|
|
95
94
|
'iphone-14-plus',
|
|
96
95
|
'iphone-14-pro',
|
|
@@ -110,10 +109,6 @@ exports.flags = {
|
|
|
110
109
|
description: '[iOS only] iOS version to run your flow against',
|
|
111
110
|
options: ['15', '16', '17', '18'],
|
|
112
111
|
}),
|
|
113
|
-
'legacy-upload': core_1.Flags.boolean({
|
|
114
|
-
default: false,
|
|
115
|
-
description: 'Use the legacy direct upload method',
|
|
116
|
-
}),
|
|
117
112
|
'maestro-version': core_1.Flags.string({
|
|
118
113
|
aliases: ['maestroVersion'],
|
|
119
114
|
description: '[ALPHA pre-release] - Maestro version to run your flow against',
|
|
@@ -146,13 +141,8 @@ exports.flags = {
|
|
|
146
141
|
}),
|
|
147
142
|
};
|
|
148
143
|
exports.iOSCompatibilityLookup = {
|
|
149
|
-
'ipad-pro-6th-gen': ['16', '17'],
|
|
150
|
-
'iphone-
|
|
151
|
-
'iphone-12-mini': ['15', '16', '17'],
|
|
152
|
-
'iphone-12-pro-max': ['15', '16', '17'],
|
|
153
|
-
'iphone-13': ['15', '16', '17'],
|
|
154
|
-
'iphone-13-mini': ['15', '16', '17'],
|
|
155
|
-
'iphone-13-pro-max': ['15', '16', '17'],
|
|
144
|
+
'ipad-pro-6th-gen': ['16', '17', '18'],
|
|
145
|
+
'iphone-13': ['15'],
|
|
156
146
|
'iphone-14': ['16', '17', '18'],
|
|
157
147
|
'iphone-14-plus': ['16', '17', '18'],
|
|
158
148
|
'iphone-14-pro': ['16', '17', '18'],
|
package/dist/methods.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export declare const typeSafePost: <T extends keyof paths>(baseUrl: string, path
|
|
|
7
7
|
body?: BodyInit;
|
|
8
8
|
headers?: HeadersInit;
|
|
9
9
|
}) => Promise<paths[T]["post"]["responses"]["201"]["content"]["application/json"]>;
|
|
10
|
+
export declare const typeSafePostDownload: (baseUrl: string, path: string, init?: {
|
|
11
|
+
body?: BodyInit;
|
|
12
|
+
headers?: HeadersInit;
|
|
13
|
+
}) => Promise<void>;
|
|
10
14
|
export declare const typeSafeGet: <T extends keyof paths>(baseUrl: string, path: string, init?: {
|
|
11
15
|
body?: FormData;
|
|
12
16
|
headers?: HeadersInit;
|
|
@@ -17,4 +21,5 @@ export declare const compressFolderToBlob: (sourceDir: string) => Promise<Blob>;
|
|
|
17
21
|
export declare const compressFilesFromRelativePath: (path: string, files: string[]) => Promise<Buffer>;
|
|
18
22
|
export declare const verifyAppZip: (zipPath: string) => Promise<void>;
|
|
19
23
|
export declare const extractAppMetadataAndroid: (appFilePath: string) => Promise<TAppMetadata>;
|
|
20
|
-
export declare const
|
|
24
|
+
export declare const extractAppMetadataIosZip: (appFilePath: string) => Promise<TAppMetadata>;
|
|
25
|
+
export declare const extractAppMetadataIos: (appFolderPath: string) => Promise<TAppMetadata>;
|
package/dist/methods.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractAppMetadataIos = exports.extractAppMetadataAndroid = exports.verifyAppZip = exports.compressFilesFromRelativePath = exports.compressFolderToBlob = exports.compressDir = exports.toBuffer = exports.typeSafeGet = exports.typeSafePost = exports.versionCheck = void 0;
|
|
3
|
+
exports.extractAppMetadataIos = exports.extractAppMetadataIosZip = exports.extractAppMetadataAndroid = exports.verifyAppZip = exports.compressFilesFromRelativePath = exports.compressFolderToBlob = exports.compressDir = exports.toBuffer = exports.typeSafeGet = exports.typeSafePostDownload = exports.typeSafePost = exports.versionCheck = void 0;
|
|
4
4
|
const cli_ux_1 = require("@oclif/core/lib/cli-ux");
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6
6
|
// @ts-ignore
|
|
7
7
|
const AppInfoParser = require("app-info-parser");
|
|
8
8
|
const archiver = require("archiver");
|
|
9
9
|
const bplist_parser_1 = require("bplist-parser");
|
|
10
|
-
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const promises_1 = require("node:fs/promises");
|
|
11
12
|
const nodePath = require("node:path");
|
|
12
13
|
const node_stream_1 = require("node:stream");
|
|
14
|
+
const promises_2 = require("node:stream/promises");
|
|
13
15
|
const StreamZip = require("node-stream-zip");
|
|
14
16
|
const plist_1 = require("plist");
|
|
15
17
|
const PERMITTED_EXTENSIONS = new Set([
|
|
@@ -47,6 +49,19 @@ const typeSafePost = async (baseUrl, path, init) => {
|
|
|
47
49
|
return res.json();
|
|
48
50
|
};
|
|
49
51
|
exports.typeSafePost = typeSafePost;
|
|
52
|
+
const typeSafePostDownload = async (baseUrl, path, init) => {
|
|
53
|
+
const res = await fetch(baseUrl + path, {
|
|
54
|
+
...init,
|
|
55
|
+
method: 'POST',
|
|
56
|
+
});
|
|
57
|
+
if (!res.ok) {
|
|
58
|
+
throw new Error(await res.text());
|
|
59
|
+
}
|
|
60
|
+
const fileStream = (0, node_fs_1.createWriteStream)('./artifacts.zip', { flags: 'wx' });
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
await (0, promises_2.finished)(node_stream_1.Readable.fromWeb(res.body).pipe(fileStream));
|
|
63
|
+
};
|
|
64
|
+
exports.typeSafePostDownload = typeSafePostDownload;
|
|
50
65
|
const typeSafeGet = async (baseUrl, path, init) => {
|
|
51
66
|
const res = await fetch(baseUrl + path, init);
|
|
52
67
|
if (!res.ok) {
|
|
@@ -139,7 +154,23 @@ const extractAppMetadataAndroid = async (appFilePath) => {
|
|
|
139
154
|
return { appId: result.package, platform: 'android' };
|
|
140
155
|
};
|
|
141
156
|
exports.extractAppMetadataAndroid = extractAppMetadataAndroid;
|
|
142
|
-
const
|
|
157
|
+
const parseInfoPlist = async (buffer) => {
|
|
158
|
+
let data;
|
|
159
|
+
const bufferType = buffer[0];
|
|
160
|
+
if (bufferType === 60 ||
|
|
161
|
+
bufferType === '<' ||
|
|
162
|
+
bufferType === 239) {
|
|
163
|
+
data = (0, plist_1.parse)(buffer.toString());
|
|
164
|
+
}
|
|
165
|
+
else if (bufferType === 98) {
|
|
166
|
+
data = (0, bplist_parser_1.parseBuffer)(buffer)[0];
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
throw new Error('Unknown plist buffer type.');
|
|
170
|
+
}
|
|
171
|
+
return data;
|
|
172
|
+
};
|
|
173
|
+
const extractAppMetadataIosZip = async (appFilePath) => new Promise((resolve, reject) => {
|
|
143
174
|
const zip = new StreamZip({ file: './' + appFilePath });
|
|
144
175
|
zip.on('ready', () => {
|
|
145
176
|
const infoPlist = Object.values(zip.entries()).find((e) => e.name.includes('Info.plist'));
|
|
@@ -147,26 +178,25 @@ const extractAppMetadataIos = async (appFilePath) => new Promise((resolve, rejec
|
|
|
147
178
|
reject(new Error('Failed to find info plist'));
|
|
148
179
|
}
|
|
149
180
|
const buffer = zip.entryDataSync(infoPlist.name);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
else if (bufferType === 98) {
|
|
158
|
-
data = (0, bplist_parser_1.parseBuffer)(buffer)[0];
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
reject(new Error('Unknown plist buffer type.'));
|
|
162
|
-
}
|
|
163
|
-
const appId = data.CFBundleIdentifier;
|
|
164
|
-
zip.close();
|
|
165
|
-
resolve({ appId, platform: 'ios' });
|
|
181
|
+
parseInfoPlist(buffer)
|
|
182
|
+
.then((data) => {
|
|
183
|
+
const appId = data.CFBundleIdentifier;
|
|
184
|
+
zip.close();
|
|
185
|
+
resolve({ appId, platform: 'ios' });
|
|
186
|
+
})
|
|
187
|
+
.catch(reject);
|
|
166
188
|
});
|
|
167
189
|
zip.on('error', (err) => {
|
|
168
190
|
console.error(err);
|
|
169
191
|
reject(err);
|
|
170
192
|
});
|
|
171
193
|
});
|
|
194
|
+
exports.extractAppMetadataIosZip = extractAppMetadataIosZip;
|
|
195
|
+
const extractAppMetadataIos = async (appFolderPath) => {
|
|
196
|
+
const infoPlistPath = nodePath.join(appFolderPath, 'Info.plist');
|
|
197
|
+
const buffer = await (0, promises_1.readFile)(infoPlistPath);
|
|
198
|
+
const data = await parseInfoPlist(buffer);
|
|
199
|
+
const appId = data.CFBundleIdentifier;
|
|
200
|
+
return { appId, platform: 'ios' };
|
|
201
|
+
};
|
|
172
202
|
exports.extractAppMetadataIos = extractAppMetadataIos;
|
package/oclif.manifest.json
CHANGED
|
@@ -106,6 +106,17 @@
|
|
|
106
106
|
"multiple": false,
|
|
107
107
|
"type": "option"
|
|
108
108
|
},
|
|
109
|
+
"download-artifacts": {
|
|
110
|
+
"description": "BETA (API may change) - 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.",
|
|
111
|
+
"name": "download-artifacts",
|
|
112
|
+
"hasDynamicHelp": false,
|
|
113
|
+
"multiple": false,
|
|
114
|
+
"options": [
|
|
115
|
+
"ALL",
|
|
116
|
+
"FAILED"
|
|
117
|
+
],
|
|
118
|
+
"type": "option"
|
|
119
|
+
},
|
|
109
120
|
"env": {
|
|
110
121
|
"char": "e",
|
|
111
122
|
"description": "One or more environment variables to inject into your flows",
|
|
@@ -166,12 +177,7 @@
|
|
|
166
177
|
"hasDynamicHelp": false,
|
|
167
178
|
"multiple": false,
|
|
168
179
|
"options": [
|
|
169
|
-
"iphone-12",
|
|
170
|
-
"iphone-12-mini",
|
|
171
|
-
"iphone-12-pro-max",
|
|
172
180
|
"iphone-13",
|
|
173
|
-
"iphone-13-mini",
|
|
174
|
-
"iphone-13-pro-max",
|
|
175
181
|
"iphone-14",
|
|
176
182
|
"iphone-14-plus",
|
|
177
183
|
"iphone-14-pro",
|
|
@@ -201,12 +207,6 @@
|
|
|
201
207
|
],
|
|
202
208
|
"type": "option"
|
|
203
209
|
},
|
|
204
|
-
"legacy-upload": {
|
|
205
|
-
"description": "Use the legacy direct upload method",
|
|
206
|
-
"name": "legacy-upload",
|
|
207
|
-
"allowNo": false,
|
|
208
|
-
"type": "boolean"
|
|
209
|
-
},
|
|
210
210
|
"maestro-version": {
|
|
211
211
|
"aliases": [
|
|
212
212
|
"maestroVersion"
|
|
@@ -275,5 +275,5 @@
|
|
|
275
275
|
]
|
|
276
276
|
}
|
|
277
277
|
},
|
|
278
|
-
"version": "1.0.
|
|
278
|
+
"version": "1.0.11"
|
|
279
279
|
}
|