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

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 (97) hide show
  1. package/README.md +40 -2
  2. package/dist/commands/artifacts.d.ts +47 -18
  3. package/dist/commands/artifacts.js +68 -60
  4. package/dist/commands/cloud.d.ts +228 -88
  5. package/dist/commands/cloud.js +389 -288
  6. package/dist/commands/list.d.ts +39 -38
  7. package/dist/commands/list.js +122 -127
  8. package/dist/commands/live.d.ts +2 -0
  9. package/dist/commands/live.js +513 -0
  10. package/dist/commands/login.d.ts +17 -0
  11. package/dist/commands/login.js +250 -0
  12. package/dist/commands/logout.d.ts +2 -0
  13. package/dist/commands/logout.js +32 -0
  14. package/dist/commands/status.d.ts +23 -42
  15. package/dist/commands/status.js +162 -173
  16. package/dist/commands/switch-org.d.ts +12 -0
  17. package/dist/commands/switch-org.js +78 -0
  18. package/dist/commands/upgrade.d.ts +2 -0
  19. package/dist/commands/upgrade.js +122 -0
  20. package/dist/commands/upload.d.ts +33 -18
  21. package/dist/commands/upload.js +62 -67
  22. package/dist/commands/whoami.d.ts +2 -0
  23. package/dist/commands/whoami.js +34 -0
  24. package/dist/config/environments.d.ts +31 -0
  25. package/dist/config/environments.js +58 -0
  26. package/dist/config/flags/api.flags.d.ts +10 -2
  27. package/dist/config/flags/api.flags.js +12 -10
  28. package/dist/config/flags/binary.flags.d.ts +17 -4
  29. package/dist/config/flags/binary.flags.js +13 -14
  30. package/dist/config/flags/device.flags.d.ts +49 -11
  31. package/dist/config/flags/device.flags.js +41 -33
  32. package/dist/config/flags/environment.flags.d.ts +27 -6
  33. package/dist/config/flags/environment.flags.js +23 -25
  34. package/dist/config/flags/execution.flags.d.ts +35 -8
  35. package/dist/config/flags/execution.flags.js +30 -37
  36. package/dist/config/flags/github.flags.d.ts +23 -5
  37. package/dist/config/flags/github.flags.js +18 -11
  38. package/dist/config/flags/output.flags.d.ts +57 -13
  39. package/dist/config/flags/output.flags.js +47 -43
  40. package/dist/constants.d.ts +218 -51
  41. package/dist/constants.js +2 -2
  42. package/dist/gateways/api-gateway.d.ts +43 -12
  43. package/dist/gateways/api-gateway.js +240 -100
  44. package/dist/gateways/cli-auth-gateway.d.ts +13 -0
  45. package/dist/gateways/cli-auth-gateway.js +57 -0
  46. package/dist/gateways/supabase-gateway.d.ts +11 -11
  47. package/dist/gateways/supabase-gateway.js +15 -39
  48. package/dist/index.d.ts +2 -1
  49. package/dist/index.js +93 -2
  50. package/dist/methods.d.ts +3 -5
  51. package/dist/methods.js +170 -178
  52. package/dist/services/device-validation.service.d.ts +8 -0
  53. package/dist/services/device-validation.service.js +55 -35
  54. package/dist/services/execution-plan.service.js +27 -15
  55. package/dist/services/execution-plan.utils.d.ts +3 -0
  56. package/dist/services/execution-plan.utils.js +10 -32
  57. package/dist/services/metadata-extractor.service.d.ts +0 -2
  58. package/dist/services/metadata-extractor.service.js +57 -57
  59. package/dist/services/moropo.service.js +25 -24
  60. package/dist/services/report-download.service.d.ts +12 -1
  61. package/dist/services/report-download.service.js +31 -20
  62. package/dist/services/results-polling.service.d.ts +6 -7
  63. package/dist/services/results-polling.service.js +80 -33
  64. package/dist/services/telemetry.service.d.ts +40 -0
  65. package/dist/services/telemetry.service.js +230 -0
  66. package/dist/services/test-submission.service.js +2 -1
  67. package/dist/services/version.service.d.ts +3 -2
  68. package/dist/services/version.service.js +27 -11
  69. package/dist/types/domain/auth.types.d.ts +12 -0
  70. package/dist/types/{schema.types.js → domain/auth.types.js} +0 -1
  71. package/dist/types/domain/live.types.d.ts +76 -0
  72. package/dist/types/domain/live.types.js +4 -0
  73. package/dist/utils/auth.d.ts +13 -0
  74. package/dist/utils/auth.js +142 -0
  75. package/dist/utils/cli.d.ts +35 -0
  76. package/dist/utils/cli.js +127 -0
  77. package/dist/utils/compatibility.d.ts +2 -1
  78. package/dist/utils/compatibility.js +2 -2
  79. package/dist/utils/config-store.d.ts +35 -0
  80. package/dist/utils/config-store.js +125 -0
  81. package/dist/utils/connectivity.js +7 -3
  82. package/dist/utils/expo.js +14 -3
  83. package/dist/utils/orgs.d.ts +11 -0
  84. package/dist/utils/orgs.js +40 -0
  85. package/dist/utils/paths.d.ts +11 -0
  86. package/dist/utils/paths.js +24 -0
  87. package/dist/utils/progress.d.ts +13 -0
  88. package/dist/utils/progress.js +50 -0
  89. package/dist/utils/styling.d.ts +13 -5
  90. package/dist/utils/styling.js +37 -7
  91. package/package.json +26 -38
  92. package/bin/dev.cmd +0 -3
  93. package/bin/dev.js +0 -6
  94. package/bin/run.cmd +0 -3
  95. package/bin/run.js +0 -7
  96. package/dist/types/schema.types.d.ts +0 -2702
  97. 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
+ from: {
3
+ type: "string";
4
+ description: string;
5
+ };
6
+ json: {
7
+ type: "boolean";
8
+ description: string;
9
+ };
10
+ limit: {
11
+ type: "string";
12
+ default: string;
13
+ description: string;
14
+ };
15
+ name: {
16
+ type: "string";
17
+ description: string;
18
+ };
19
+ offset: {
20
+ type: "string";
21
+ default: string;
22
+ description: string;
23
+ };
24
+ to: {
25
+ type: "string";
26
+ description: string;
27
+ };
28
+ '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
+ '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,138 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const core_1 = require("@oclif/core");
4
- const constants_1 = require("../constants");
3
+ exports.listCommand = void 0;
4
+ const citty_1 = require("citty");
5
+ const api_flags_1 = require("../config/flags/api.flags");
5
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");
6
10
  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',
11
+ function detectShellExpansion(name) {
12
+ const indicators = [
13
+ name.includes('/') || name.includes('\\'),
14
+ /\.(yaml|yml|json|txt|md|ts|js|py|sh)$/i.test(name),
15
+ name.includes(' ') && !name.includes('*') && !name.includes('?'),
16
16
  ];
17
- static flags = {
18
- apiKey: constants_1.flags.apiKey,
19
- apiUrl: constants_1.flags.apiUrl,
20
- from: core_1.Flags.string({
17
+ if (indicators.some(Boolean)) {
18
+ cli_1.logger.warn(`\nThe --name parameter appears to have been expanded by your shell: "${name}"\n` +
19
+ 'Wildcards like * should be quoted to prevent shell expansion.\n' +
20
+ 'Examples:\n' +
21
+ ' ✓ Correct: dcd list --name "nightly-*"\n' +
22
+ " ✓ Correct: dcd list --name 'nightly-*'\n" +
23
+ ' ✗ Incorrect: dcd list --name nightly-*\n');
24
+ }
25
+ }
26
+ function displayResults(response) {
27
+ const { uploads, total, limit, offset } = response;
28
+ if (uploads.length === 0) {
29
+ cli_1.logger.log(`\n${styling_1.symbols.info} No uploads found matching your criteria.\n`);
30
+ return;
31
+ }
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('');
38
+ for (const upload of uploads) {
39
+ const date = new Date(upload.created_at);
40
+ const formattedDate = date.toLocaleDateString('en-US', {
41
+ day: 'numeric',
42
+ hour: '2-digit',
43
+ minute: '2-digit',
44
+ month: 'short',
45
+ year: 'numeric',
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('');
53
+ }
54
+ if (total > offset + uploads.length) {
55
+ 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`);
57
+ }
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`);
59
+ }
60
+ exports.listCommand = (0, citty_1.defineCommand)({
61
+ meta: {
62
+ name: 'list',
63
+ description: 'List recent flow uploads for your organization',
64
+ },
65
+ args: {
66
+ ...api_flags_1.apiFlags,
67
+ from: {
68
+ type: 'string',
21
69
  description: 'Filter uploads created on or after this date (ISO 8601 format, e.g., 2024-01-01)',
22
- }),
23
- json: core_1.Flags.boolean({
70
+ },
71
+ json: {
72
+ type: 'boolean',
24
73
  description: 'Output in JSON format',
25
- }),
26
- limit: core_1.Flags.integer({
27
- default: 20,
74
+ },
75
+ limit: {
76
+ type: 'string',
77
+ default: '20',
28
78
  description: 'Maximum number of uploads to return',
29
- }),
30
- name: core_1.Flags.string({
79
+ },
80
+ name: {
81
+ type: 'string',
31
82
  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,
83
+ },
84
+ offset: {
85
+ type: 'string',
86
+ default: '0',
35
87
  description: 'Number of uploads to skip (for pagination)',
36
- }),
37
- to: core_1.Flags.string({
88
+ },
89
+ to: {
90
+ type: 'string',
38
91
  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
- }
92
+ },
93
+ },
94
+ async run({ args }) {
95
+ const apiKeyFlag = args['api-key'];
96
+ const apiUrl = (0, config_store_1.resolveApiUrl)(args['api-url']);
97
+ const from = args.from;
98
+ const to = args.to;
99
+ const name = args.name;
100
+ 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;
62
103
  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;
104
+ const auth = await (0, auth_1.resolveAuth)({ apiKeyFlag });
105
+ 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).');
107
+ }
108
+ 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).');
110
+ }
111
+ if (name) {
112
+ detectShellExpansion(name);
113
+ }
114
+ try {
115
+ const response = (await api_gateway_1.ApiGateway.listUploads(apiUrl, auth, {
116
+ from,
117
+ limit,
118
+ name,
119
+ offset,
120
+ to,
121
+ }));
122
+ if (json) {
123
+ // eslint-disable-next-line no-console
124
+ console.log(JSON.stringify(response, null, 2));
125
+ return;
126
+ }
127
+ displayResults(response);
128
+ }
129
+ catch (error) {
130
+ throw new cli_1.CliError(`Failed to list uploads: ${error.message}`);
72
131
  }
73
- this.displayResults(response);
74
132
  }
75
133
  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;
108
- }
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('');
134
+ cli_1.logger.error(error, { exit: 1, json });
133
135
  }
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;
136
+ },
137
+ });
138
+ exports.default = exports.listCommand;
@@ -0,0 +1,2 @@
1
+ export declare const liveCommand: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ export default liveCommand;