@devicecloud.dev/dcd 4.1.2 → 4.1.4

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 (47) hide show
  1. package/dist/commands/cloud.d.ts +26 -34
  2. package/dist/commands/cloud.js +151 -513
  3. package/dist/config/flags/api.flags.d.ts +7 -0
  4. package/dist/config/flags/api.flags.js +19 -0
  5. package/dist/config/flags/binary.flags.d.ts +8 -0
  6. package/dist/config/flags/binary.flags.js +20 -0
  7. package/dist/config/flags/device.flags.d.ts +14 -0
  8. package/dist/config/flags/device.flags.js +46 -0
  9. package/dist/config/flags/environment.flags.d.ts +11 -0
  10. package/dist/config/flags/environment.flags.js +37 -0
  11. package/dist/config/flags/execution.flags.d.ts +13 -0
  12. package/dist/config/flags/execution.flags.js +50 -0
  13. package/dist/config/flags/output.flags.d.ts +18 -0
  14. package/dist/config/flags/output.flags.js +61 -0
  15. package/dist/constants.d.ts +28 -24
  16. package/dist/constants.js +21 -206
  17. package/dist/gateways/api-gateway.d.ts +3 -3
  18. package/dist/gateways/api-gateway.js +1 -1
  19. package/dist/methods.d.ts +0 -4
  20. package/dist/methods.js +15 -80
  21. package/dist/services/device-validation.service.d.ts +31 -0
  22. package/dist/services/device-validation.service.js +74 -0
  23. package/dist/{plan.d.ts → services/execution-plan.service.d.ts} +10 -2
  24. package/dist/{plan.js → services/execution-plan.service.js} +12 -11
  25. package/dist/{planMethods.js → services/execution-plan.utils.js} +0 -1
  26. package/dist/services/metadata-extractor.service.d.ts +46 -0
  27. package/dist/services/metadata-extractor.service.js +138 -0
  28. package/dist/services/moropo.service.d.ts +25 -0
  29. package/dist/services/moropo.service.js +118 -0
  30. package/dist/services/report-download.service.d.ts +43 -0
  31. package/dist/services/report-download.service.js +113 -0
  32. package/dist/services/results-polling.service.d.ts +51 -0
  33. package/dist/services/results-polling.service.js +224 -0
  34. package/dist/services/test-submission.service.d.ts +47 -0
  35. package/dist/services/test-submission.service.js +122 -0
  36. package/dist/services/version.service.d.ts +32 -0
  37. package/dist/services/version.service.js +82 -0
  38. package/dist/types/{schema.types.d.ts → generated/schema.types.d.ts} +349 -349
  39. package/dist/types/index.d.ts +6 -0
  40. package/dist/types/index.js +24 -0
  41. package/dist/utils/compatibility.d.ts +5 -0
  42. package/oclif.manifest.json +195 -209
  43. package/package.json +2 -9
  44. /package/dist/{planMethods.d.ts → services/execution-plan.utils.d.ts} +0 -0
  45. /package/dist/types/{device.types.d.ts → domain/device.types.d.ts} +0 -0
  46. /package/dist/types/{device.types.js → domain/device.types.js} +0 -0
  47. /package/dist/types/{schema.types.js → generated/schema.types.js} +0 -0
@@ -0,0 +1,122 @@
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
+ const envObject = this.parseKeyValuePairs(env);
24
+ const metadataObject = this.parseKeyValuePairs(metadata);
25
+ if (Object.keys(envObject).length > 0) {
26
+ this.logDebug(debug, logger, `DEBUG: Environment variables: ${JSON.stringify(envObject)}`);
27
+ }
28
+ if (Object.keys(metadataObject).length > 0) {
29
+ this.logDebug(debug, logger, `DEBUG: User metadata: ${JSON.stringify(metadataObject)}`);
30
+ }
31
+ this.logDebug(debug, logger, `DEBUG: Compressing files from path: ${flowFile}`);
32
+ const buffer = await (0, methods_1.compressFilesFromRelativePath)(flowFile?.endsWith('.yaml') || flowFile?.endsWith('.yml')
33
+ ? path.dirname(flowFile)
34
+ : flowFile, [
35
+ ...new Set([
36
+ ...referencedFiles,
37
+ ...testFileNames,
38
+ ...sequentialFlows,
39
+ ]),
40
+ ], commonRoot);
41
+ this.logDebug(debug, logger, `DEBUG: Compressed file size: ${buffer.length} bytes`);
42
+ const blob = new Blob([buffer], {
43
+ type: mimeTypeLookupByExtension.zip,
44
+ });
45
+ testFormData.set('file', blob, 'flowFile.zip');
46
+ testFormData.set('appBinaryId', appBinaryId);
47
+ testFormData.set('testFileNames', JSON.stringify(this.normalizePaths(testFileNames, commonRoot)));
48
+ testFormData.set('flowMetadata', JSON.stringify(this.normalizePathMap(flowMetadata, commonRoot)));
49
+ testFormData.set('testFileOverrides', JSON.stringify(this.normalizePathMap(flowOverrides, commonRoot)));
50
+ testFormData.set('sequentialFlows', JSON.stringify(this.normalizePaths(sequentialFlows, commonRoot)));
51
+ testFormData.set('env', JSON.stringify(envObject));
52
+ testFormData.set('googlePlay', googlePlay ? 'true' : 'false');
53
+ const configPayload = {
54
+ allExcludeTags,
55
+ allIncludeTags,
56
+ autoRetriesRemaining: retry,
57
+ continueOnFailure,
58
+ deviceLocale,
59
+ maestroVersion,
60
+ mitmHost,
61
+ mitmPath,
62
+ orientation,
63
+ raw: JSON.stringify(raw),
64
+ report,
65
+ showCrosshairs,
66
+ skipChromeOnboarding,
67
+ version: cliVersion,
68
+ };
69
+ testFormData.set('config', JSON.stringify(configPayload));
70
+ if (Object.keys(metadataObject).length > 0) {
71
+ const metadataPayload = { userMetadata: metadataObject };
72
+ testFormData.set('metadata', JSON.stringify(metadataPayload));
73
+ this.logDebug(debug, logger, `DEBUG: Sending metadata to API: ${JSON.stringify(metadataPayload)}`);
74
+ }
75
+ this.setOptionalFields(testFormData, {
76
+ androidApiLevel,
77
+ androidDevice,
78
+ iOSDevice,
79
+ iOSVersion,
80
+ name,
81
+ runnerType,
82
+ });
83
+ if (workspaceConfig) {
84
+ testFormData.set('workspaceConfig', JSON.stringify(workspaceConfig));
85
+ }
86
+ return testFormData;
87
+ }
88
+ logDebug(debug, logger, message) {
89
+ if (debug && logger) {
90
+ logger(message);
91
+ }
92
+ }
93
+ normalizeFilePath(filePath, commonRoot) {
94
+ return filePath.replaceAll(commonRoot, '.').split(path.sep).join('/');
95
+ }
96
+ normalizePathMap(map, commonRoot) {
97
+ return Object.fromEntries(Object.entries(map).map(([key, value]) => [
98
+ this.normalizeFilePath(key, commonRoot),
99
+ value,
100
+ ]));
101
+ }
102
+ normalizePaths(paths, commonRoot) {
103
+ return paths.map((p) => this.normalizeFilePath(p, commonRoot));
104
+ }
105
+ parseKeyValuePairs(pairs) {
106
+ // eslint-disable-next-line unicorn/no-array-reduce
107
+ return pairs.reduce((acc, cur) => {
108
+ const [key, ...value] = cur.split('=');
109
+ // handle case where value includes an equals sign
110
+ acc[key] = value.join('=');
111
+ return acc;
112
+ }, {});
113
+ }
114
+ setOptionalFields(formData, fields) {
115
+ for (const [key, value] of Object.entries(fields)) {
116
+ if (value) {
117
+ formData.set(key, value.toString());
118
+ }
119
+ }
120
+ }
121
+ }
122
+ exports.TestSubmissionService = TestSubmissionService;
@@ -0,0 +1,32 @@
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 options - Configuration options
23
+ * @param options.debug - Enable debug logging
24
+ * @param options.logger - Optional logger function
25
+ * @returns Validated Maestro version string
26
+ * @throws Error if version is not supported
27
+ */
28
+ resolveMaestroVersion(requestedVersion: string | undefined, compatibilityData: CompatibilityData, options?: {
29
+ debug?: boolean;
30
+ logger?: (message: string) => void;
31
+ }): string;
32
+ }
@@ -0,0 +1,82 @@
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 options - Configuration options
48
+ * @param options.debug - Enable debug logging
49
+ * @param options.logger - Optional logger function
50
+ * @returns Validated Maestro version string
51
+ * @throws Error if version is not supported
52
+ */
53
+ resolveMaestroVersion(requestedVersion, compatibilityData, options) {
54
+ const { debug = false, logger } = options || {};
55
+ const log = logger || console.log;
56
+ const { supportedVersions, defaultVersion, latestVersion } = compatibilityData.maestro;
57
+ // Resolve "latest" to actual latest version from API
58
+ let resolvedVersion = requestedVersion;
59
+ if (requestedVersion === 'latest') {
60
+ resolvedVersion = latestVersion;
61
+ if (debug) {
62
+ log(`DEBUG: Resolved "latest" to ${latestVersion}`);
63
+ }
64
+ }
65
+ else if (!requestedVersion) {
66
+ resolvedVersion = defaultVersion;
67
+ if (debug) {
68
+ log(`DEBUG: Using default Maestro version ${defaultVersion}`);
69
+ }
70
+ }
71
+ // Validate Maestro version
72
+ if (!supportedVersions.includes(resolvedVersion)) {
73
+ throw new Error(`Maestro version ${resolvedVersion} is not supported. Supported versions: ${supportedVersions.join(', ')}`);
74
+ }
75
+ if (debug) {
76
+ log(`DEBUG: Maestro version validated: ${resolvedVersion}`);
77
+ log(`DEBUG: Supported Maestro versions: ${supportedVersions.join(', ')}`);
78
+ }
79
+ return resolvedVersion;
80
+ }
81
+ }
82
+ exports.VersionService = VersionService;