@devicecloud.dev/dcd 4.1.2-beta.1 → 4.1.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.
Files changed (50) hide show
  1. package/dist/commands/cloud.d.ts +26 -34
  2. package/dist/commands/cloud.js +117 -465
  3. package/dist/commands/status.d.ts +6 -0
  4. package/dist/commands/status.js +19 -1
  5. package/dist/config/flags/api.flags.d.ts +7 -0
  6. package/dist/config/flags/api.flags.js +19 -0
  7. package/dist/config/flags/binary.flags.d.ts +8 -0
  8. package/dist/config/flags/binary.flags.js +20 -0
  9. package/dist/config/flags/device.flags.d.ts +14 -0
  10. package/dist/config/flags/device.flags.js +46 -0
  11. package/dist/config/flags/environment.flags.d.ts +11 -0
  12. package/dist/config/flags/environment.flags.js +37 -0
  13. package/dist/config/flags/execution.flags.d.ts +13 -0
  14. package/dist/config/flags/execution.flags.js +50 -0
  15. package/dist/config/flags/output.flags.d.ts +18 -0
  16. package/dist/config/flags/output.flags.js +61 -0
  17. package/dist/constants.d.ts +28 -24
  18. package/dist/constants.js +21 -206
  19. package/dist/gateways/api-gateway.d.ts +3 -3
  20. package/dist/methods.d.ts +0 -4
  21. package/dist/methods.js +15 -80
  22. package/dist/services/device-validation.service.d.ts +29 -0
  23. package/dist/services/device-validation.service.js +72 -0
  24. package/dist/{plan.d.ts → services/execution-plan.service.d.ts} +1 -1
  25. package/dist/{plan.js → services/execution-plan.service.js} +10 -10
  26. package/dist/{planMethods.js → services/execution-plan.utils.js} +0 -1
  27. package/dist/services/metadata-extractor.service.d.ts +46 -0
  28. package/dist/services/metadata-extractor.service.js +138 -0
  29. package/dist/services/moropo.service.d.ts +20 -0
  30. package/dist/services/moropo.service.js +113 -0
  31. package/dist/services/report-download.service.d.ts +40 -0
  32. package/dist/services/report-download.service.js +110 -0
  33. package/dist/services/results-polling.service.d.ts +45 -0
  34. package/dist/services/results-polling.service.js +210 -0
  35. package/dist/services/test-submission.service.d.ts +41 -0
  36. package/dist/services/test-submission.service.js +116 -0
  37. package/dist/services/version.service.d.ts +31 -0
  38. package/dist/services/version.service.js +81 -0
  39. package/dist/types/{schema.types.d.ts → generated/schema.types.d.ts} +349 -349
  40. package/dist/types/index.d.ts +6 -0
  41. package/dist/types/index.js +24 -0
  42. package/dist/utils/compatibility.d.ts +5 -0
  43. package/dist/utils/connectivity.d.ts +29 -0
  44. package/dist/utils/connectivity.js +100 -0
  45. package/oclif.manifest.json +195 -209
  46. package/package.json +2 -9
  47. /package/dist/{planMethods.d.ts → services/execution-plan.utils.d.ts} +0 -0
  48. /package/dist/types/{device.types.d.ts → domain/device.types.d.ts} +0 -0
  49. /package/dist/types/{device.types.js → domain/device.types.js} +0 -0
  50. /package/dist/types/{schema.types.js → generated/schema.types.js} +0 -0
@@ -0,0 +1,41 @@
1
+ import { IExecutionPlan } from './execution-plan.service';
2
+ export interface TestSubmissionConfig {
3
+ androidApiLevel?: string;
4
+ androidDevice?: string;
5
+ appBinaryId: string;
6
+ cliVersion: string;
7
+ commonRoot: string;
8
+ continueOnFailure?: boolean;
9
+ debug?: boolean;
10
+ deviceLocale?: string;
11
+ env?: string[];
12
+ executionPlan: IExecutionPlan;
13
+ flowFile: string;
14
+ googlePlay?: boolean;
15
+ iOSDevice?: string;
16
+ iOSVersion?: string;
17
+ logger?: (message: string) => void;
18
+ maestroVersion: string;
19
+ metadata?: string[];
20
+ mitmHost?: string;
21
+ mitmPath?: string;
22
+ name?: string;
23
+ orientation?: string;
24
+ raw?: unknown;
25
+ report?: string;
26
+ retry?: number;
27
+ runnerType?: string;
28
+ showCrosshairs?: boolean;
29
+ skipChromeOnboarding?: boolean;
30
+ }
31
+ /**
32
+ * Service for building test submission form data
33
+ */
34
+ export declare class TestSubmissionService {
35
+ /**
36
+ * Build FormData for test submission
37
+ * @param config Test submission configuration
38
+ * @returns FormData ready to be submitted to the API
39
+ */
40
+ buildTestFormData(config: TestSubmissionConfig): Promise<FormData>;
41
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestSubmissionService = void 0;
4
+ const path = require("node:path");
5
+ const methods_1 = require("../methods");
6
+ const mimeTypeLookupByExtension = {
7
+ zip: 'application/zip',
8
+ };
9
+ /**
10
+ * Service for building test submission form data
11
+ */
12
+ class TestSubmissionService {
13
+ /**
14
+ * Build FormData for test submission
15
+ * @param config Test submission configuration
16
+ * @returns FormData ready to be submitted to the API
17
+ */
18
+ async buildTestFormData(config) {
19
+ const { appBinaryId, flowFile, executionPlan, commonRoot, cliVersion, env = [], metadata = [], googlePlay = false, androidApiLevel, androidDevice, iOSVersion, iOSDevice, name, runnerType, maestroVersion, deviceLocale, orientation, mitmHost, mitmPath, retry, continueOnFailure = true, report, showCrosshairs, skipChromeOnboarding, raw, debug = false, logger, } = config;
20
+ const { allExcludeTags, allIncludeTags, flowMetadata, flowOverrides, flowsToRun: testFileNames, referencedFiles, sequence, workspaceConfig, } = executionPlan;
21
+ const { flows: sequentialFlows = [] } = sequence ?? {};
22
+ const testFormData = new FormData();
23
+ // eslint-disable-next-line unicorn/no-array-reduce
24
+ const envObject = env.reduce((acc, cur) => {
25
+ const [key, ...value] = cur.split('=');
26
+ // handle case where value includes an equals sign
27
+ acc[key] = value.join('=');
28
+ return acc;
29
+ }, {});
30
+ // eslint-disable-next-line unicorn/no-array-reduce
31
+ const metadataObject = metadata.reduce((acc, cur) => {
32
+ const [key, ...value] = cur.split('=');
33
+ // handle case where value includes an equals sign
34
+ acc[key] = value.join('=');
35
+ return acc;
36
+ }, {});
37
+ if (debug && logger && Object.keys(envObject).length > 0) {
38
+ logger(`DEBUG: Environment variables: ${JSON.stringify(envObject)}`);
39
+ }
40
+ if (debug && logger && Object.keys(metadataObject).length > 0) {
41
+ logger(`DEBUG: User metadata: ${JSON.stringify(metadataObject)}`);
42
+ }
43
+ if (debug && logger) {
44
+ logger(`DEBUG: Compressing files from path: ${flowFile}`);
45
+ }
46
+ const buffer = await (0, methods_1.compressFilesFromRelativePath)(flowFile?.endsWith('.yaml') || flowFile?.endsWith('.yml')
47
+ ? path.dirname(flowFile)
48
+ : flowFile, [
49
+ ...new Set([
50
+ ...referencedFiles,
51
+ ...testFileNames,
52
+ ...sequentialFlows,
53
+ ]),
54
+ ], commonRoot);
55
+ if (debug && logger) {
56
+ logger(`DEBUG: Compressed file size: ${buffer.length} bytes`);
57
+ }
58
+ const blob = new Blob([buffer], {
59
+ type: mimeTypeLookupByExtension.zip,
60
+ });
61
+ testFormData.set('file', blob, 'flowFile.zip');
62
+ testFormData.set('appBinaryId', appBinaryId);
63
+ testFormData.set('testFileNames', JSON.stringify(testFileNames.map((t) => t.replaceAll(commonRoot, '.').split(path.sep).join('/'))));
64
+ testFormData.set('flowMetadata', JSON.stringify(Object.fromEntries(Object.entries(flowMetadata).map(([key, value]) => [
65
+ key.replaceAll(commonRoot, '.').split(path.sep).join('/'),
66
+ value,
67
+ ]))));
68
+ testFormData.set('testFileOverrides', JSON.stringify(Object.fromEntries(Object.entries(flowOverrides).map(([key, value]) => [
69
+ key.replaceAll(commonRoot, '.').split(path.sep).join('/'),
70
+ value,
71
+ ]))));
72
+ testFormData.set('sequentialFlows', JSON.stringify(sequentialFlows.map((t) => t.replaceAll(commonRoot, '.').split(path.sep).join('/'))));
73
+ testFormData.set('env', JSON.stringify(envObject));
74
+ testFormData.set('googlePlay', googlePlay ? 'true' : 'false');
75
+ const configPayload = {
76
+ allExcludeTags,
77
+ allIncludeTags,
78
+ autoRetriesRemaining: retry,
79
+ continueOnFailure,
80
+ deviceLocale,
81
+ maestroVersion,
82
+ mitmHost,
83
+ mitmPath,
84
+ orientation,
85
+ raw: JSON.stringify(raw),
86
+ report,
87
+ showCrosshairs,
88
+ skipChromeOnboarding,
89
+ version: cliVersion,
90
+ };
91
+ testFormData.set('config', JSON.stringify(configPayload));
92
+ if (Object.keys(metadataObject).length > 0) {
93
+ const metadataPayload = { userMetadata: metadataObject };
94
+ testFormData.set('metadata', JSON.stringify(metadataPayload));
95
+ if (debug && logger) {
96
+ logger(`DEBUG: Sending metadata to API: ${JSON.stringify(metadataPayload)}`);
97
+ }
98
+ }
99
+ if (androidApiLevel)
100
+ testFormData.set('androidApiLevel', androidApiLevel.toString());
101
+ if (androidDevice)
102
+ testFormData.set('androidDevice', androidDevice.toString());
103
+ if (iOSVersion)
104
+ testFormData.set('iOSVersion', iOSVersion.toString());
105
+ if (iOSDevice)
106
+ testFormData.set('iOSDevice', iOSDevice.toString());
107
+ if (name)
108
+ testFormData.set('name', name.toString());
109
+ if (runnerType)
110
+ testFormData.set('runnerType', runnerType.toString());
111
+ if (workspaceConfig)
112
+ testFormData.set('workspaceConfig', JSON.stringify(workspaceConfig));
113
+ return testFormData;
114
+ }
115
+ }
116
+ exports.TestSubmissionService = TestSubmissionService;
@@ -0,0 +1,31 @@
1
+ import { CompatibilityData } from '../utils/compatibility';
2
+ /**
3
+ * Service for handling version validation and checking
4
+ */
5
+ export declare class VersionService {
6
+ /**
7
+ * Check npm registry for the latest published version of the CLI
8
+ * @returns Latest version string or null if check fails
9
+ */
10
+ checkLatestCliVersion(): Promise<null | string>;
11
+ /**
12
+ * Compare two semantic version strings
13
+ * @param current - Current version
14
+ * @param latest - Latest version
15
+ * @returns true if current is older than latest
16
+ */
17
+ isOutdated(current: string, latest: string): boolean;
18
+ /**
19
+ * Resolve and validate Maestro version against API compatibility data
20
+ * @param requestedVersion - Version requested by user (or undefined for default)
21
+ * @param compatibilityData - API compatibility data
22
+ * @param debug - Enable debug logging
23
+ * @param logger - Optional logger function
24
+ * @returns Validated Maestro version string
25
+ * @throws Error if version is not supported
26
+ */
27
+ resolveMaestroVersion(requestedVersion: string | undefined, compatibilityData: CompatibilityData, options?: {
28
+ debug?: boolean;
29
+ logger?: (message: string) => void;
30
+ }): string;
31
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VersionService = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ /**
6
+ * Service for handling version validation and checking
7
+ */
8
+ class VersionService {
9
+ /**
10
+ * Check npm registry for the latest published version of the CLI
11
+ * @returns Latest version string or null if check fails
12
+ */
13
+ async checkLatestCliVersion() {
14
+ try {
15
+ const latestVersion = (0, node_child_process_1.execSync)('npm view @devicecloud.dev/dcd version', {
16
+ encoding: 'utf8',
17
+ stdio: ['ignore', 'pipe', 'ignore'],
18
+ }).trim();
19
+ return latestVersion;
20
+ }
21
+ catch {
22
+ // Silently fail - version check is informational only
23
+ return null;
24
+ }
25
+ }
26
+ /**
27
+ * Compare two semantic version strings
28
+ * @param current - Current version
29
+ * @param latest - Latest version
30
+ * @returns true if current is older than latest
31
+ */
32
+ isOutdated(current, latest) {
33
+ const currentParts = current.split('.').map(Number);
34
+ const latestParts = latest.split('.').map(Number);
35
+ for (let i = 0; i < 3; i++) {
36
+ if (currentParts[i] < latestParts[i])
37
+ return true;
38
+ if (currentParts[i] > latestParts[i])
39
+ return false;
40
+ }
41
+ return false;
42
+ }
43
+ /**
44
+ * Resolve and validate Maestro version against API compatibility data
45
+ * @param requestedVersion - Version requested by user (or undefined for default)
46
+ * @param compatibilityData - API compatibility data
47
+ * @param debug - Enable debug logging
48
+ * @param logger - Optional logger function
49
+ * @returns Validated Maestro version string
50
+ * @throws Error if version is not supported
51
+ */
52
+ resolveMaestroVersion(requestedVersion, compatibilityData, options) {
53
+ const { debug = false, logger } = options || {};
54
+ const log = logger || console.log;
55
+ const { supportedVersions, defaultVersion, latestVersion } = compatibilityData.maestro;
56
+ // Resolve "latest" to actual latest version from API
57
+ let resolvedVersion = requestedVersion;
58
+ if (requestedVersion === 'latest') {
59
+ resolvedVersion = latestVersion;
60
+ if (debug) {
61
+ log(`DEBUG: Resolved "latest" to ${latestVersion}`);
62
+ }
63
+ }
64
+ else if (!requestedVersion) {
65
+ resolvedVersion = defaultVersion;
66
+ if (debug) {
67
+ log(`DEBUG: Using default Maestro version ${defaultVersion}`);
68
+ }
69
+ }
70
+ // Validate Maestro version
71
+ if (!supportedVersions.includes(resolvedVersion)) {
72
+ throw new Error(`Maestro version ${resolvedVersion} is not supported. Supported versions: ${supportedVersions.join(', ')}`);
73
+ }
74
+ if (debug) {
75
+ log(`DEBUG: Maestro version validated: ${resolvedVersion}`);
76
+ log(`DEBUG: Supported Maestro versions: ${supportedVersions.join(', ')}`);
77
+ }
78
+ return resolvedVersion;
79
+ }
80
+ }
81
+ exports.VersionService = VersionService;