@devicecloud.dev/dcd 4.4.9 → 5.0.0-beta.1

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 (130) hide show
  1. package/README.md +75 -2
  2. package/dist/commands/artifacts.d.ts +47 -18
  3. package/dist/commands/artifacts.js +69 -64
  4. package/dist/commands/cloud.d.ts +228 -88
  5. package/dist/commands/cloud.js +430 -342
  6. package/dist/commands/list.d.ts +39 -38
  7. package/dist/commands/list.js +124 -131
  8. package/dist/commands/live.d.ts +2 -0
  9. package/dist/commands/live.js +520 -0
  10. package/dist/commands/login.d.ts +17 -0
  11. package/dist/commands/login.js +252 -0
  12. package/dist/commands/logout.d.ts +2 -0
  13. package/dist/commands/logout.js +30 -0
  14. package/dist/commands/status.d.ts +23 -42
  15. package/dist/commands/status.js +170 -179
  16. package/dist/commands/switch-org.d.ts +12 -0
  17. package/dist/commands/switch-org.js +76 -0
  18. package/dist/commands/upgrade.d.ts +2 -0
  19. package/dist/commands/upgrade.js +120 -0
  20. package/dist/commands/upload.d.ts +33 -18
  21. package/dist/commands/upload.js +72 -78
  22. package/dist/commands/whoami.d.ts +2 -0
  23. package/dist/commands/whoami.js +31 -0
  24. package/dist/config/environments.d.ts +31 -0
  25. package/dist/config/environments.js +52 -0
  26. package/dist/config/flags/api.flags.d.ts +10 -2
  27. package/dist/config/flags/api.flags.js +13 -14
  28. package/dist/config/flags/binary.flags.d.ts +17 -4
  29. package/dist/config/flags/binary.flags.js +14 -18
  30. package/dist/config/flags/device.flags.d.ts +49 -11
  31. package/dist/config/flags/device.flags.js +43 -38
  32. package/dist/config/flags/environment.flags.d.ts +27 -6
  33. package/dist/config/flags/environment.flags.js +24 -29
  34. package/dist/config/flags/execution.flags.d.ts +35 -8
  35. package/dist/config/flags/execution.flags.js +31 -41
  36. package/dist/config/flags/github.flags.d.ts +23 -5
  37. package/dist/config/flags/github.flags.js +19 -15
  38. package/dist/config/flags/output.flags.d.ts +57 -13
  39. package/dist/config/flags/output.flags.js +48 -47
  40. package/dist/constants.d.ts +218 -51
  41. package/dist/constants.js +17 -20
  42. package/dist/gateways/api-gateway.d.ts +72 -16
  43. package/dist/gateways/api-gateway.js +298 -104
  44. package/dist/gateways/cli-auth-gateway.d.ts +13 -0
  45. package/dist/gateways/cli-auth-gateway.js +54 -0
  46. package/dist/gateways/realtime-gateway.d.ts +32 -0
  47. package/dist/gateways/realtime-gateway.js +103 -0
  48. package/dist/gateways/supabase-gateway.d.ts +11 -11
  49. package/dist/gateways/supabase-gateway.js +20 -48
  50. package/dist/index.d.ts +2 -1
  51. package/dist/index.js +98 -4
  52. package/dist/mcp/context.d.ts +33 -0
  53. package/dist/mcp/context.js +33 -0
  54. package/dist/mcp/helpers.d.ts +16 -0
  55. package/dist/mcp/helpers.js +34 -0
  56. package/dist/mcp/index.d.ts +2 -0
  57. package/dist/mcp/index.js +24 -0
  58. package/dist/mcp/server.d.ts +7 -0
  59. package/dist/mcp/server.js +27 -0
  60. package/dist/mcp/tools/download-artifacts.d.ts +11 -0
  61. package/dist/mcp/tools/download-artifacts.js +84 -0
  62. package/dist/mcp/tools/get-status.d.ts +7 -0
  63. package/dist/mcp/tools/get-status.js +39 -0
  64. package/dist/mcp/tools/list-devices.d.ts +7 -0
  65. package/dist/mcp/tools/list-devices.js +27 -0
  66. package/dist/mcp/tools/list-runs.d.ts +3 -0
  67. package/dist/mcp/tools/list-runs.js +60 -0
  68. package/dist/mcp/tools/run-cloud-test.d.ts +14 -0
  69. package/dist/mcp/tools/run-cloud-test.js +233 -0
  70. package/dist/methods.d.ts +34 -5
  71. package/dist/methods.js +266 -215
  72. package/dist/services/device-validation.service.d.ts +9 -1
  73. package/dist/services/device-validation.service.js +56 -40
  74. package/dist/services/execution-plan.service.js +40 -31
  75. package/dist/services/execution-plan.utils.d.ts +3 -0
  76. package/dist/services/execution-plan.utils.js +25 -55
  77. package/dist/services/flow-paths.d.ts +17 -0
  78. package/dist/services/flow-paths.js +52 -0
  79. package/dist/services/metadata-extractor.service.d.ts +0 -2
  80. package/dist/services/metadata-extractor.service.js +75 -78
  81. package/dist/services/moropo.service.js +33 -34
  82. package/dist/services/report-download.service.d.ts +12 -1
  83. package/dist/services/report-download.service.js +34 -27
  84. package/dist/services/results-polling.service.d.ts +23 -9
  85. package/dist/services/results-polling.service.js +257 -123
  86. package/dist/services/telemetry.service.d.ts +49 -0
  87. package/dist/services/telemetry.service.js +252 -0
  88. package/dist/services/test-submission.service.d.ts +21 -4
  89. package/dist/services/test-submission.service.js +51 -33
  90. package/dist/services/version.service.d.ts +4 -3
  91. package/dist/services/version.service.js +28 -16
  92. package/dist/types/domain/auth.types.d.ts +20 -0
  93. package/dist/types/domain/auth.types.js +1 -0
  94. package/dist/types/domain/device.types.js +8 -11
  95. package/dist/types/domain/live.types.d.ts +76 -0
  96. package/dist/types/domain/live.types.js +3 -0
  97. package/dist/types/generated/schema.types.js +1 -2
  98. package/dist/types/index.d.ts +2 -2
  99. package/dist/types/index.js +2 -18
  100. package/dist/types.js +1 -2
  101. package/dist/utils/auth.d.ts +13 -0
  102. package/dist/utils/auth.js +141 -0
  103. package/dist/utils/ci.d.ts +12 -0
  104. package/dist/utils/ci.js +39 -0
  105. package/dist/utils/cli.d.ts +35 -0
  106. package/dist/utils/cli.js +118 -0
  107. package/dist/utils/compatibility.d.ts +2 -1
  108. package/dist/utils/compatibility.js +6 -8
  109. package/dist/utils/config-store.d.ts +35 -0
  110. package/dist/utils/config-store.js +115 -0
  111. package/dist/utils/connectivity.js +8 -7
  112. package/dist/utils/expo.js +29 -24
  113. package/dist/utils/orgs.d.ts +11 -0
  114. package/dist/utils/orgs.js +36 -0
  115. package/dist/utils/paths.d.ts +11 -0
  116. package/dist/utils/paths.js +21 -0
  117. package/dist/utils/progress.d.ts +13 -0
  118. package/dist/utils/progress.js +47 -0
  119. package/dist/utils/styling.d.ts +42 -36
  120. package/dist/utils/styling.js +78 -82
  121. package/dist/utils/ui.d.ts +41 -0
  122. package/dist/utils/ui.js +95 -0
  123. package/package.json +36 -45
  124. package/bin/dev.cmd +0 -3
  125. package/bin/dev.js +0 -6
  126. package/bin/run.cmd +0 -3
  127. package/bin/run.js +0 -7
  128. package/dist/types/schema.types.d.ts +0 -2702
  129. package/dist/types/schema.types.js +0 -3
  130. package/oclif.manifest.json +0 -884
@@ -1,38 +1,39 @@
1
- import { Command } from '@oclif/core';
2
- type UploadListItem = {
3
- consoleUrl: string;
4
- created_at: string;
5
- id: string;
6
- name: null | string;
7
- };
8
- type ListResponse = {
9
- limit: number;
10
- offset: number;
11
- total: number;
12
- uploads: UploadListItem[];
13
- };
14
- export default class List extends Command {
15
- static description: string;
16
- static enableJsonFlag: boolean;
17
- static examples: string[];
18
- static flags: {
19
- apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
20
- apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
21
- from: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
22
- json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
- limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
24
- name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
25
- offset: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
26
- to: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
27
- };
28
- run(): Promise<ListResponse | void>;
29
- /**
30
- * Detects if the provided name parameter likely underwent shell expansion
31
- * Warns the user if shell expansion is detected
32
- * @param name - The name parameter to check for shell expansion
33
- * @returns void
34
- */
35
- private detectShellExpansion;
36
- private displayResults;
37
- }
38
- export {};
1
+ export declare const listCommand: import("citty").CommandDef<{
2
+ readonly from: {
3
+ readonly type: "string";
4
+ readonly description: "Filter uploads created on or after this date (ISO 8601 format, e.g., 2024-01-01)";
5
+ };
6
+ readonly json: {
7
+ readonly type: "boolean";
8
+ readonly description: "Output in JSON format";
9
+ };
10
+ readonly limit: {
11
+ readonly type: "string";
12
+ readonly default: "20";
13
+ readonly description: "Maximum number of uploads to return";
14
+ };
15
+ readonly name: {
16
+ readonly type: "string";
17
+ readonly description: "Filter by upload name (supports * wildcard, e.g., \"nightly-*\"). IMPORTANT: Always quote wildcards to prevent shell expansion!";
18
+ };
19
+ readonly offset: {
20
+ readonly type: "string";
21
+ readonly default: "0";
22
+ readonly description: "Number of uploads to skip (for pagination)";
23
+ };
24
+ readonly to: {
25
+ readonly type: "string";
26
+ readonly description: "Filter uploads created on or before this date (ISO 8601 format, e.g., 2024-01-31)";
27
+ };
28
+ readonly 'api-key': {
29
+ readonly type: "string";
30
+ readonly alias: ["apiKey"];
31
+ readonly description: "API key for devicecloud.dev (find this in the console UI). You can also set the DEVICE_CLOUD_API_KEY environment variable.";
32
+ };
33
+ readonly 'api-url': {
34
+ readonly type: "string";
35
+ readonly alias: ["apiURL", "apiUrl"];
36
+ readonly description: "API base URL (defaults to the URL stored by `dcd login`, else prod)";
37
+ };
38
+ }>;
39
+ export default listCommand;
@@ -1,143 +1,136 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const core_1 = require("@oclif/core");
4
- const constants_1 = require("../constants");
5
- const api_gateway_1 = require("../gateways/api-gateway");
6
- const styling_1 = require("../utils/styling");
7
- class List extends core_1.Command {
8
- static description = 'List recent flow uploads for your organization';
9
- static enableJsonFlag = true;
10
- static examples = [
11
- '<%= config.bin %> <%= command.id %>',
12
- '<%= config.bin %> <%= command.id %> --limit 10',
13
- '<%= config.bin %> <%= command.id %> --name "nightly-*" # Quote wildcards to prevent shell expansion!',
14
- '<%= config.bin %> <%= command.id %> --from 2024-01-01 --to 2024-01-31',
15
- '<%= config.bin %> <%= command.id %> --json',
1
+ import { defineCommand } from 'citty';
2
+ import { apiFlags } from '../config/flags/api.flags.js';
3
+ import { ApiGateway } from '../gateways/api-gateway.js';
4
+ import { resolveAuth } from '../utils/auth.js';
5
+ import { CliError, logger, parseIntFlag } from '../utils/cli.js';
6
+ import { resolveApiUrl } from '../utils/config-store.js';
7
+ import { colors, formatId, formatUrl } from '../utils/styling.js';
8
+ import { ui } from '../utils/ui.js';
9
+ function detectShellExpansion(name) {
10
+ const indicators = [
11
+ name.includes('/') || name.includes('\\'),
12
+ /\.(yaml|yml|json|txt|md|ts|js|py|sh)$/i.test(name),
13
+ name.includes(' ') && !name.includes('*') && !name.includes('?'),
16
14
  ];
17
- static flags = {
18
- apiKey: constants_1.flags.apiKey,
19
- apiUrl: constants_1.flags.apiUrl,
20
- from: core_1.Flags.string({
15
+ if (indicators.some(Boolean)) {
16
+ logger.warn(`\nThe --name parameter appears to have been expanded by your shell: "${name}"\n` +
17
+ 'Wildcards like * should be quoted to prevent shell expansion.\n' +
18
+ 'Examples:\n' +
19
+ ' ✓ Correct: dcd list --name "nightly-*"\n' +
20
+ " ✓ Correct: dcd list --name 'nightly-*'\n" +
21
+ ' ✗ Incorrect: dcd list --name nightly-*\n');
22
+ }
23
+ }
24
+ function displayResults(response) {
25
+ const { uploads, total, limit, offset } = response;
26
+ if (uploads.length === 0) {
27
+ logger.log(ui.info('No uploads found matching your criteria.'));
28
+ return;
29
+ }
30
+ const offsetNote = offset > 0 ? colors.dim(`, offset ${offset}`) : '';
31
+ logger.log(ui.section('Recent Uploads'));
32
+ logger.log(ui.note(` showing ${uploads.length} of ${total}${offsetNote}`));
33
+ for (const upload of uploads) {
34
+ const date = new Date(upload.created_at);
35
+ const formattedDate = date.toLocaleDateString('en-US', {
36
+ day: 'numeric',
37
+ hour: '2-digit',
38
+ minute: '2-digit',
39
+ month: 'short',
40
+ year: 'numeric',
41
+ });
42
+ const displayName = upload.name ? colors.bold(upload.name) : colors.dim('(unnamed)');
43
+ logger.log(ui.branch([
44
+ displayName,
45
+ ...ui.fields([
46
+ ['id', formatId(upload.id)],
47
+ ['created', formattedDate],
48
+ ['console', formatUrl(upload.consoleUrl)],
49
+ ]),
50
+ ]));
51
+ }
52
+ if (total > offset + uploads.length) {
53
+ const remaining = total - (offset + uploads.length);
54
+ logger.log(ui.note(`\nUse --offset ${offset + uploads.length} to see the next ${Math.min(remaining, limit)} uploads`));
55
+ }
56
+ logger.log(ui.info(colors.dim('Use dcd status --upload-id <id> for detailed test results')));
57
+ }
58
+ export const listCommand = defineCommand({
59
+ meta: {
60
+ name: 'list',
61
+ description: 'List recent flow uploads for your organization',
62
+ },
63
+ args: {
64
+ ...apiFlags,
65
+ from: {
66
+ type: 'string',
21
67
  description: 'Filter uploads created on or after this date (ISO 8601 format, e.g., 2024-01-01)',
22
- }),
23
- json: core_1.Flags.boolean({
68
+ },
69
+ json: {
70
+ type: 'boolean',
24
71
  description: 'Output in JSON format',
25
- }),
26
- limit: core_1.Flags.integer({
27
- default: 20,
72
+ },
73
+ limit: {
74
+ type: 'string',
75
+ default: '20',
28
76
  description: 'Maximum number of uploads to return',
29
- }),
30
- name: core_1.Flags.string({
77
+ },
78
+ name: {
79
+ type: 'string',
31
80
  description: 'Filter by upload name (supports * wildcard, e.g., "nightly-*"). IMPORTANT: Always quote wildcards to prevent shell expansion!',
32
- }),
33
- offset: core_1.Flags.integer({
34
- default: 0,
81
+ },
82
+ offset: {
83
+ type: 'string',
84
+ default: '0',
35
85
  description: 'Number of uploads to skip (for pagination)',
36
- }),
37
- to: core_1.Flags.string({
86
+ },
87
+ to: {
88
+ type: 'string',
38
89
  description: 'Filter uploads created on or before this date (ISO 8601 format, e.g., 2024-01-31)',
39
- }),
40
- };
41
- async run() {
42
- const { flags } = await this.parse(List);
43
- const { apiKey: apiKeyFlag, apiUrl, from, json, limit, name, offset, to, } = flags;
44
- const apiKey = apiKeyFlag || process.env.DEVICE_CLOUD_API_KEY;
45
- if (!apiKey) {
46
- this.error('API key is required. Please provide it via --api-key flag or DEVICE_CLOUD_API_KEY environment variable.');
47
- return;
48
- }
49
- // Validate date formats if provided
50
- if (from && Number.isNaN(Date.parse(from))) {
51
- this.error('Invalid --from date format. Please use ISO 8601 format (e.g., 2024-01-01).');
52
- return;
53
- }
54
- if (to && Number.isNaN(Date.parse(to))) {
55
- this.error('Invalid --to date format. Please use ISO 8601 format (e.g., 2024-01-31).');
56
- return;
57
- }
58
- // Detect potential shell expansion of wildcards
59
- if (name) {
60
- this.detectShellExpansion(name);
61
- }
90
+ },
91
+ },
92
+ async run({ args }) {
93
+ const apiKeyFlag = args['api-key'];
94
+ const apiUrl = resolveApiUrl(args['api-url']);
95
+ const from = args.from;
96
+ const to = args.to;
97
+ const name = args.name;
98
+ const json = Boolean(args.json);
99
+ const limit = parseIntFlag(args.limit, 'limit') ?? 20;
100
+ const offset = parseIntFlag(args.offset, 'offset') ?? 0;
62
101
  try {
63
- const response = await api_gateway_1.ApiGateway.listUploads(apiUrl, apiKey, {
64
- from,
65
- limit,
66
- name,
67
- offset,
68
- to,
69
- });
70
- if (json) {
71
- return response;
102
+ const auth = await resolveAuth({ apiKeyFlag });
103
+ if (from && Number.isNaN(Date.parse(from))) {
104
+ throw new CliError('Invalid --from date format. Please use ISO 8601 format (e.g., 2024-01-01).');
105
+ }
106
+ if (to && Number.isNaN(Date.parse(to))) {
107
+ throw new CliError('Invalid --to date format. Please use ISO 8601 format (e.g., 2024-01-31).');
108
+ }
109
+ if (name) {
110
+ detectShellExpansion(name);
111
+ }
112
+ try {
113
+ const response = (await ApiGateway.listUploads(apiUrl, auth, {
114
+ from,
115
+ limit,
116
+ name,
117
+ offset,
118
+ to,
119
+ }));
120
+ if (json) {
121
+ // eslint-disable-next-line no-console
122
+ console.log(JSON.stringify(response, null, 2));
123
+ return;
124
+ }
125
+ displayResults(response);
126
+ }
127
+ catch (error) {
128
+ throw new CliError(`Failed to list uploads: ${error.message}`);
72
129
  }
73
- this.displayResults(response);
74
130
  }
75
131
  catch (error) {
76
- this.error(`Failed to list uploads: ${error.message}`);
77
- }
78
- }
79
- /**
80
- * Detects if the provided name parameter likely underwent shell expansion
81
- * Warns the user if shell expansion is detected
82
- * @param name - The name parameter to check for shell expansion
83
- * @returns void
84
- */
85
- detectShellExpansion(name) {
86
- const shellExpansionIndicators = [
87
- // Contains file path separators (likely expanded to file paths)
88
- name.includes('/') || name.includes('\\'),
89
- // Contains file extensions (likely expanded to filenames)
90
- /\.(yaml|yml|json|txt|md|ts|js|py|sh)$/i.test(name),
91
- // Looks like multiple space-separated filenames (shell expanded glob to multiple files)
92
- name.includes(' ') && !name.includes('*') && !name.includes('?'),
93
- ];
94
- if (shellExpansionIndicators.some(Boolean)) {
95
- this.warn(`\nThe --name parameter appears to have been expanded by your shell: "${name}"\n` +
96
- 'Wildcards like * should be quoted to prevent shell expansion.\n' +
97
- 'Examples:\n' +
98
- ' ✓ Correct: dcd list --name "nightly-*"\n' +
99
- ' ✓ Correct: dcd list --name \'nightly-*\'\n' +
100
- ' ✗ Incorrect: dcd list --name nightly-*\n');
101
- }
102
- }
103
- displayResults(response) {
104
- const { uploads, total, limit, offset } = response;
105
- if (uploads.length === 0) {
106
- this.log('\nNo uploads found matching your criteria.\n');
107
- return;
132
+ logger.error(error, { exit: 1, json });
108
133
  }
109
- this.log((0, styling_1.sectionHeader)('Recent Uploads'));
110
- this.log(` ${styling_1.colors.dim('Showing')} ${uploads.length} ${styling_1.colors.dim('of')} ${total} ${styling_1.colors.dim('uploads')}`);
111
- if (offset > 0) {
112
- this.log(` ${styling_1.colors.dim('(offset:')} ${offset}${styling_1.colors.dim(')')}`);
113
- }
114
- this.log('');
115
- for (const upload of uploads) {
116
- const date = new Date(upload.created_at);
117
- const formattedDate = date.toLocaleDateString('en-US', {
118
- day: 'numeric',
119
- hour: '2-digit',
120
- minute: '2-digit',
121
- month: 'short',
122
- year: 'numeric',
123
- });
124
- // Upload name
125
- const displayName = upload.name || styling_1.colors.dim('(unnamed)');
126
- this.log(` ${styling_1.colors.bold(displayName)}`);
127
- // Upload ID and date
128
- this.log(` ${styling_1.colors.dim('ID:')} ${(0, styling_1.formatId)(upload.id)}`);
129
- this.log(` ${styling_1.colors.dim('Created:')} ${formattedDate}`);
130
- // Console URL
131
- this.log(` ${styling_1.colors.dim('Console:')} ${(0, styling_1.formatUrl)(upload.consoleUrl)}`);
132
- this.log('');
133
- }
134
- // Pagination hint
135
- if (total > offset + uploads.length) {
136
- const remaining = total - (offset + uploads.length);
137
- this.log(` ${styling_1.colors.dim('Use')} --offset ${offset + limit} ${styling_1.colors.dim('to see the next')} ${Math.min(remaining, limit)} ${styling_1.colors.dim('uploads')}\n`);
138
- }
139
- // Hint about getting detailed status
140
- this.log(` ${styling_1.colors.dim('Tip: Use')} dcd status --upload-id <id> ${styling_1.colors.dim('for detailed test results')}\n`);
141
- }
142
- }
143
- exports.default = List;
134
+ },
135
+ });
136
+ export default listCommand;
@@ -0,0 +1,2 @@
1
+ export declare const liveCommand: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ export default liveCommand;