@devicecloud.dev/dcd 5.0.0-beta.0 → 5.0.0-beta.2

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 (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +52 -0
  3. package/dist/commands/artifacts.d.ts +28 -28
  4. package/dist/commands/artifacts.js +20 -23
  5. package/dist/commands/cloud.d.ts +57 -57
  6. package/dist/commands/cloud.js +224 -192
  7. package/dist/commands/list.d.ts +22 -22
  8. package/dist/commands/list.js +43 -40
  9. package/dist/commands/live.js +134 -127
  10. package/dist/commands/login.d.ts +11 -11
  11. package/dist/commands/login.js +46 -44
  12. package/dist/commands/logout.js +16 -18
  13. package/dist/commands/status.d.ts +11 -11
  14. package/dist/commands/status.js +53 -44
  15. package/dist/commands/switch-org.d.ts +7 -7
  16. package/dist/commands/switch-org.js +19 -21
  17. package/dist/commands/upgrade.js +41 -33
  18. package/dist/commands/upload.d.ts +10 -10
  19. package/dist/commands/upload.js +42 -43
  20. package/dist/commands/whoami.js +17 -20
  21. package/dist/config/environments.js +6 -12
  22. package/dist/config/flags/api.flags.js +1 -4
  23. package/dist/config/flags/binary.flags.js +1 -4
  24. package/dist/config/flags/device.flags.js +6 -9
  25. package/dist/config/flags/environment.flags.js +1 -4
  26. package/dist/config/flags/execution.flags.js +1 -4
  27. package/dist/config/flags/github.flags.js +1 -4
  28. package/dist/config/flags/output.flags.js +1 -4
  29. package/dist/constants.js +15 -18
  30. package/dist/gateways/api-gateway.d.ts +31 -6
  31. package/dist/gateways/api-gateway.js +70 -16
  32. package/dist/gateways/cli-auth-gateway.d.ts +1 -1
  33. package/dist/gateways/cli-auth-gateway.js +3 -6
  34. package/dist/gateways/realtime-gateway.d.ts +32 -0
  35. package/dist/gateways/realtime-gateway.js +103 -0
  36. package/dist/gateways/supabase-gateway.d.ts +1 -1
  37. package/dist/gateways/supabase-gateway.js +10 -14
  38. package/dist/index.js +41 -38
  39. package/dist/mcp/context.d.ts +33 -0
  40. package/dist/mcp/context.js +33 -0
  41. package/dist/mcp/helpers.d.ts +16 -0
  42. package/dist/mcp/helpers.js +34 -0
  43. package/dist/mcp/index.d.ts +2 -0
  44. package/dist/mcp/index.js +24 -0
  45. package/dist/mcp/server.d.ts +7 -0
  46. package/dist/mcp/server.js +27 -0
  47. package/dist/mcp/tools/download-artifacts.d.ts +11 -0
  48. package/dist/mcp/tools/download-artifacts.js +84 -0
  49. package/dist/mcp/tools/get-status.d.ts +7 -0
  50. package/dist/mcp/tools/get-status.js +39 -0
  51. package/dist/mcp/tools/list-devices.d.ts +7 -0
  52. package/dist/mcp/tools/list-devices.js +27 -0
  53. package/dist/mcp/tools/list-runs.d.ts +3 -0
  54. package/dist/mcp/tools/list-runs.js +60 -0
  55. package/dist/mcp/tools/run-cloud-test.d.ts +14 -0
  56. package/dist/mcp/tools/run-cloud-test.js +233 -0
  57. package/dist/methods.d.ts +32 -1
  58. package/dist/methods.js +133 -79
  59. package/dist/services/device-validation.service.d.ts +1 -1
  60. package/dist/services/device-validation.service.js +1 -5
  61. package/dist/services/execution-plan.service.js +14 -17
  62. package/dist/services/execution-plan.utils.js +15 -23
  63. package/dist/services/flow-paths.d.ts +17 -0
  64. package/dist/services/flow-paths.js +52 -0
  65. package/dist/services/metadata-extractor.service.js +22 -25
  66. package/dist/services/moropo.service.js +18 -20
  67. package/dist/services/report-download.service.d.ts +1 -1
  68. package/dist/services/report-download.service.js +5 -9
  69. package/dist/services/results-polling.service.d.ts +18 -3
  70. package/dist/services/results-polling.service.js +211 -108
  71. package/dist/services/telemetry.service.d.ts +10 -1
  72. package/dist/services/telemetry.service.js +40 -18
  73. package/dist/services/test-submission.service.d.ts +21 -4
  74. package/dist/services/test-submission.service.js +51 -34
  75. package/dist/services/version.service.d.ts +30 -7
  76. package/dist/services/version.service.js +88 -32
  77. package/dist/types/domain/auth.types.d.ts +8 -0
  78. package/dist/types/domain/auth.types.js +1 -2
  79. package/dist/types/domain/device.types.js +8 -11
  80. package/dist/types/domain/live.types.js +1 -2
  81. package/dist/types/generated/schema.types.js +1 -2
  82. package/dist/types/index.d.ts +2 -2
  83. package/dist/types/index.js +2 -18
  84. package/dist/types.js +1 -2
  85. package/dist/utils/auth.d.ts +1 -1
  86. package/dist/utils/auth.js +27 -28
  87. package/dist/utils/ci.d.ts +12 -0
  88. package/dist/utils/ci.js +39 -0
  89. package/dist/utils/cli.d.ts +16 -2
  90. package/dist/utils/cli.js +57 -29
  91. package/dist/utils/compatibility.d.ts +1 -1
  92. package/dist/utils/compatibility.js +5 -7
  93. package/dist/utils/config-store.js +33 -43
  94. package/dist/utils/connectivity.js +1 -4
  95. package/dist/utils/expo.js +15 -21
  96. package/dist/utils/orgs.js +8 -12
  97. package/dist/utils/paths.js +2 -5
  98. package/dist/utils/progress.d.ts +3 -0
  99. package/dist/utils/progress.js +47 -8
  100. package/dist/utils/styling.d.ts +35 -37
  101. package/dist/utils/styling.js +52 -86
  102. package/dist/utils/ui.d.ts +41 -0
  103. package/dist/utils/ui.js +95 -0
  104. package/package.json +27 -24
@@ -1,36 +1,36 @@
1
1
  export declare const listCommand: import("citty").CommandDef<{
2
- from: {
3
- type: "string";
4
- description: string;
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
5
  };
6
- json: {
7
- type: "boolean";
8
- description: string;
6
+ readonly json: {
7
+ readonly type: "boolean";
8
+ readonly description: "Output in JSON format";
9
9
  };
10
- limit: {
11
- type: "string";
12
- default: string;
13
- description: string;
10
+ readonly limit: {
11
+ readonly type: "string";
12
+ readonly default: "20";
13
+ readonly description: "Maximum number of uploads to return";
14
14
  };
15
- name: {
16
- type: "string";
17
- description: string;
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
18
  };
19
- offset: {
20
- type: "string";
21
- default: string;
22
- description: string;
19
+ readonly offset: {
20
+ readonly type: "string";
21
+ readonly default: "0";
22
+ readonly description: "Number of uploads to skip (for pagination)";
23
23
  };
24
- to: {
25
- type: "string";
26
- description: string;
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
27
  };
28
- 'api-key': {
28
+ readonly 'api-key': {
29
29
  readonly type: "string";
30
30
  readonly alias: ["apiKey"];
31
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
32
  };
33
- 'api-url': {
33
+ readonly 'api-url': {
34
34
  readonly type: "string";
35
35
  readonly alias: ["apiURL", "apiUrl"];
36
36
  readonly description: "API base URL (defaults to the URL stored by `dcd login`, else prod)";
@@ -1,13 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.listCommand = void 0;
4
- const citty_1 = require("citty");
5
- const api_flags_1 = require("../config/flags/api.flags");
6
- const api_gateway_1 = require("../gateways/api-gateway");
7
- const auth_1 = require("../utils/auth");
8
- const cli_1 = require("../utils/cli");
9
- const config_store_1 = require("../utils/config-store");
10
- const styling_1 = require("../utils/styling");
1
+ import { defineCommand } from 'citty';
2
+ import { apiFlags } from '../config/flags/api.flags.js';
3
+ import { resolveFrontendUrl } from '../config/environments.js';
4
+ import { ApiGateway } from '../gateways/api-gateway.js';
5
+ import { resolveAuth } from '../utils/auth.js';
6
+ import { CliError, logger, parseIntFlag } from '../utils/cli.js';
7
+ import { resolveApiUrl } from '../utils/config-store.js';
8
+ import { colors, formatId, formatUrl } from '../utils/styling.js';
9
+ import { ui } from '../utils/ui.js';
11
10
  function detectShellExpansion(name) {
12
11
  const indicators = [
13
12
  name.includes('/') || name.includes('\\'),
@@ -15,7 +14,7 @@ function detectShellExpansion(name) {
15
14
  name.includes(' ') && !name.includes('*') && !name.includes('?'),
16
15
  ];
17
16
  if (indicators.some(Boolean)) {
18
- cli_1.logger.warn(`\nThe --name parameter appears to have been expanded by your shell: "${name}"\n` +
17
+ logger.warn(`\nThe --name parameter appears to have been expanded by your shell: "${name}"\n` +
19
18
  'Wildcards like * should be quoted to prevent shell expansion.\n' +
20
19
  'Examples:\n' +
21
20
  ' ✓ Correct: dcd list --name "nightly-*"\n' +
@@ -23,18 +22,19 @@ function detectShellExpansion(name) {
23
22
  ' ✗ Incorrect: dcd list --name nightly-*\n');
24
23
  }
25
24
  }
26
- function displayResults(response) {
25
+ function displayResults(response, apiUrl) {
27
26
  const { uploads, total, limit, offset } = response;
27
+ // Build console links from the env the CLI is pointed at, rather than the
28
+ // API-supplied consoleUrl (which is hardcoded to prod) — so dev/staging users
29
+ // get links that actually resolve.
30
+ const frontendUrl = resolveFrontendUrl(apiUrl);
28
31
  if (uploads.length === 0) {
29
- cli_1.logger.log(`\n${styling_1.symbols.info} No uploads found matching your criteria.\n`);
32
+ logger.log(ui.info('No uploads found matching your criteria.'));
30
33
  return;
31
34
  }
32
- cli_1.logger.log((0, styling_1.sectionHeader)('Recent Uploads'));
33
- cli_1.logger.log(` ${styling_1.colors.dim('Showing')} ${uploads.length} ${styling_1.colors.dim('of')} ${total} ${styling_1.colors.dim('uploads')}`);
34
- if (offset > 0) {
35
- cli_1.logger.log(` ${styling_1.colors.dim('(offset:')} ${offset}${styling_1.colors.dim(')')}`);
36
- }
37
- cli_1.logger.log('');
35
+ const offsetNote = offset > 0 ? colors.dim(`, offset ${offset}`) : '';
36
+ logger.log(ui.section('Recent Uploads'));
37
+ logger.log(ui.note(` showing ${uploads.length} of ${total}${offsetNote}`));
38
38
  for (const upload of uploads) {
39
39
  const date = new Date(upload.created_at);
40
40
  const formattedDate = date.toLocaleDateString('en-US', {
@@ -44,26 +44,29 @@ function displayResults(response) {
44
44
  month: 'short',
45
45
  year: 'numeric',
46
46
  });
47
- const displayName = upload.name || styling_1.colors.dim('(unnamed)');
48
- cli_1.logger.log(` ${styling_1.colors.bold(displayName)}`);
49
- cli_1.logger.log(` ${styling_1.colors.dim('ID:')} ${(0, styling_1.formatId)(upload.id)}`);
50
- cli_1.logger.log(` ${styling_1.colors.dim('Created:')} ${formattedDate}`);
51
- cli_1.logger.log(` ${styling_1.colors.dim('Console:')} ${(0, styling_1.formatUrl)(upload.consoleUrl)}`);
52
- cli_1.logger.log('');
47
+ const displayName = upload.name ? colors.bold(upload.name) : colors.dim('(unnamed)');
48
+ logger.log(ui.branch([
49
+ displayName,
50
+ ...ui.fields([
51
+ ['id', formatId(upload.id)],
52
+ ['created', formattedDate],
53
+ ['console', formatUrl(`${frontendUrl}/results?upload=${upload.id}`)],
54
+ ]),
55
+ ]));
53
56
  }
54
57
  if (total > offset + uploads.length) {
55
58
  const remaining = total - (offset + uploads.length);
56
- cli_1.logger.log(` ${styling_1.colors.dim('Use')} --offset ${offset + uploads.length} ${styling_1.colors.dim('to see the next')} ${Math.min(remaining, limit)} ${styling_1.colors.dim('uploads')}\n`);
59
+ logger.log(ui.note(`\nUse --offset ${offset + uploads.length} to see the next ${Math.min(remaining, limit)} uploads`));
57
60
  }
58
- cli_1.logger.log(` ${styling_1.symbols.info} ${styling_1.colors.dim('Use')} dcd status --upload-id <id> ${styling_1.colors.dim('for detailed test results')}\n`);
61
+ logger.log(ui.info(colors.dim('Use dcd status --upload-id <id> for detailed test results')));
59
62
  }
60
- exports.listCommand = (0, citty_1.defineCommand)({
63
+ export const listCommand = defineCommand({
61
64
  meta: {
62
65
  name: 'list',
63
66
  description: 'List recent flow uploads for your organization',
64
67
  },
65
68
  args: {
66
- ...api_flags_1.apiFlags,
69
+ ...apiFlags,
67
70
  from: {
68
71
  type: 'string',
69
72
  description: 'Filter uploads created on or after this date (ISO 8601 format, e.g., 2024-01-01)',
@@ -93,26 +96,26 @@ exports.listCommand = (0, citty_1.defineCommand)({
93
96
  },
94
97
  async run({ args }) {
95
98
  const apiKeyFlag = args['api-key'];
96
- const apiUrl = (0, config_store_1.resolveApiUrl)(args['api-url']);
99
+ const apiUrl = resolveApiUrl(args['api-url']);
97
100
  const from = args.from;
98
101
  const to = args.to;
99
102
  const name = args.name;
100
103
  const json = Boolean(args.json);
101
- const limit = (0, cli_1.parseIntFlag)(args.limit, 'limit') ?? 20;
102
- const offset = (0, cli_1.parseIntFlag)(args.offset, 'offset') ?? 0;
104
+ const limit = parseIntFlag(args.limit, 'limit') ?? 20;
105
+ const offset = parseIntFlag(args.offset, 'offset') ?? 0;
103
106
  try {
104
- const auth = await (0, auth_1.resolveAuth)({ apiKeyFlag });
107
+ const auth = await resolveAuth({ apiKeyFlag });
105
108
  if (from && Number.isNaN(Date.parse(from))) {
106
- throw new cli_1.CliError('Invalid --from date format. Please use ISO 8601 format (e.g., 2024-01-01).');
109
+ throw new CliError('Invalid --from date format. Please use ISO 8601 format (e.g., 2024-01-01).');
107
110
  }
108
111
  if (to && Number.isNaN(Date.parse(to))) {
109
- throw new cli_1.CliError('Invalid --to date format. Please use ISO 8601 format (e.g., 2024-01-31).');
112
+ throw new CliError('Invalid --to date format. Please use ISO 8601 format (e.g., 2024-01-31).');
110
113
  }
111
114
  if (name) {
112
115
  detectShellExpansion(name);
113
116
  }
114
117
  try {
115
- const response = (await api_gateway_1.ApiGateway.listUploads(apiUrl, auth, {
118
+ const response = (await ApiGateway.listUploads(apiUrl, auth, {
116
119
  from,
117
120
  limit,
118
121
  name,
@@ -124,15 +127,15 @@ exports.listCommand = (0, citty_1.defineCommand)({
124
127
  console.log(JSON.stringify(response, null, 2));
125
128
  return;
126
129
  }
127
- displayResults(response);
130
+ displayResults(response, apiUrl);
128
131
  }
129
132
  catch (error) {
130
- throw new cli_1.CliError(`Failed to list uploads: ${error.message}`);
133
+ throw new CliError(`Failed to list uploads: ${error.message}`);
131
134
  }
132
135
  }
133
136
  catch (error) {
134
- cli_1.logger.error(error, { exit: 1, json });
137
+ logger.error(error, { exit: 1, json });
135
138
  }
136
139
  },
137
140
  });
138
- exports.default = exports.listCommand;
141
+ export default listCommand;