@devicecloud.dev/dcd 4.4.4 → 4.4.5

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.
@@ -247,7 +247,6 @@
247
247
  "hasDynamicHelp": false,
248
248
  "multiple": false,
249
249
  "options": [
250
- "generic-tablet",
251
250
  "pixel-6",
252
251
  "pixel-6-pro",
253
252
  "pixel-7",
@@ -717,92 +716,6 @@
717
716
  "list.js"
718
717
  ]
719
718
  },
720
- "live": {
721
- "aliases": [],
722
- "args": {},
723
- "description": "Start and interact with a live device session",
724
- "examples": [
725
- "<%= config.bin %> <%= command.id %> start",
726
- "<%= config.bin %> <%= command.id %> start --platform android --app-binary-id abc-123",
727
- "<%= config.bin %> <%= command.id %> install --session-id 42 --app-binary-id abc-123",
728
- "<%= config.bin %> <%= command.id %> exec --session-id 42 --yaml \"- launchApp\"",
729
- "<%= config.bin %> <%= command.id %> stop --session-id 42",
730
- "<%= config.bin %> <%= command.id %> status --session-id 42"
731
- ],
732
- "flags": {
733
- "apiKey": {
734
- "aliases": [
735
- "api-key"
736
- ],
737
- "description": "API key for devicecloud.dev (find this in the console UI). You can also set the DEVICE_CLOUD_API_KEY environment variable.",
738
- "name": "apiKey",
739
- "hasDynamicHelp": false,
740
- "multiple": false,
741
- "type": "option"
742
- },
743
- "apiUrl": {
744
- "aliases": [
745
- "api-url",
746
- "apiURL"
747
- ],
748
- "description": "API base URL",
749
- "hidden": true,
750
- "name": "apiUrl",
751
- "default": "https://api.devicecloud.dev",
752
- "hasDynamicHelp": false,
753
- "multiple": false,
754
- "type": "option"
755
- },
756
- "app-binary-id": {
757
- "description": "Binary upload ID to install on the device",
758
- "name": "app-binary-id",
759
- "hasDynamicHelp": false,
760
- "multiple": false,
761
- "type": "option"
762
- },
763
- "platform": {
764
- "description": "Device platform",
765
- "name": "platform",
766
- "default": "android",
767
- "hasDynamicHelp": false,
768
- "multiple": false,
769
- "options": [
770
- "android",
771
- "ios"
772
- ],
773
- "type": "option"
774
- },
775
- "session-id": {
776
- "description": "Live session ID (required for install, exec, stop, status)",
777
- "name": "session-id",
778
- "hasDynamicHelp": false,
779
- "multiple": false,
780
- "type": "option"
781
- },
782
- "yaml": {
783
- "description": "Maestro YAML commands to execute (for exec subcommand)",
784
- "name": "yaml",
785
- "hasDynamicHelp": false,
786
- "multiple": false,
787
- "type": "option"
788
- }
789
- },
790
- "hasDynamicHelp": false,
791
- "hidden": true,
792
- "hiddenAliases": [],
793
- "id": "live",
794
- "pluginAlias": "@devicecloud.dev/dcd",
795
- "pluginName": "@devicecloud.dev/dcd",
796
- "pluginType": "core",
797
- "strict": false,
798
- "enableJsonFlag": false,
799
- "isESM": false,
800
- "relativePath": [
801
- "dist",
802
- "commands",
803
- "live.js"
804
- ]
805
- },
806
719
  "status": {
807
720
  "aliases": [],
808
721
  "args": {},
@@ -966,5 +879,5 @@
966
879
  ]
967
880
  }
968
881
  },
969
- "version": "4.4.4"
882
+ "version": "4.4.5"
970
883
  }
package/package.json CHANGED
@@ -69,7 +69,7 @@
69
69
  "type": "git",
70
70
  "url": "https://devicecloud.dev"
71
71
  },
72
- "version": "4.4.4",
72
+ "version": "4.4.5",
73
73
  "bugs": {
74
74
  "url": "https://discord.gg/gm3mJwcNw8"
75
75
  },
@@ -1,22 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class Live extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
8
- 'app-binary-id': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
- platform: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
- 'session-id': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
11
- yaml: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
12
- };
13
- static hidden: boolean;
14
- static strict: boolean;
15
- run(): Promise<void>;
16
- private execTest;
17
- private getFrontendUrl;
18
- private getStatus;
19
- private installBinary;
20
- private startSession;
21
- private stopSession;
22
- }
@@ -1,207 +0,0 @@
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 Live extends core_1.Command {
8
- static description = 'Start and interact with a live device session';
9
- static examples = [
10
- '<%= config.bin %> <%= command.id %> start',
11
- '<%= config.bin %> <%= command.id %> start --platform android --app-binary-id abc-123',
12
- '<%= config.bin %> <%= command.id %> install --session-id 42 --app-binary-id abc-123',
13
- '<%= config.bin %> <%= command.id %> exec --session-id 42 --yaml "- launchApp"',
14
- '<%= config.bin %> <%= command.id %> stop --session-id 42',
15
- '<%= config.bin %> <%= command.id %> status --session-id 42',
16
- ];
17
- static flags = {
18
- apiKey: constants_1.flags.apiKey,
19
- apiUrl: constants_1.flags.apiUrl,
20
- 'app-binary-id': core_1.Flags.string({
21
- description: 'Binary upload ID to install on the device',
22
- }),
23
- platform: core_1.Flags.string({
24
- default: 'android',
25
- description: 'Device platform',
26
- options: ['android', 'ios'],
27
- }),
28
- 'session-id': core_1.Flags.integer({
29
- description: 'Live session ID (required for install, exec, stop, status)',
30
- }),
31
- yaml: core_1.Flags.string({
32
- description: 'Maestro YAML commands to execute (for exec subcommand)',
33
- }),
34
- };
35
- static hidden = true;
36
- static strict = false;
37
- async run() {
38
- const { argv, flags } = await this.parse(Live);
39
- const { apiKey: apiKeyFlag, apiUrl, 'app-binary-id': binaryId, platform, 'session-id': sessionId, yaml, } = flags;
40
- const subcommand = argv[0];
41
- if (!subcommand || !['exec', 'install', 'start', 'status', 'stop'].includes(subcommand)) {
42
- this.log((0, styling_1.sectionHeader)('Live Session Commands'));
43
- this.log(` ${styling_1.colors.bold('start')} Start a new live device session`);
44
- this.log(` ${styling_1.colors.bold('install')} Install a binary on the device`);
45
- this.log(` ${styling_1.colors.bold('exec')} Execute Maestro YAML commands`);
46
- this.log(` ${styling_1.colors.bold('stop')} Stop a live session`);
47
- this.log(` ${styling_1.colors.bold('status')} Get session status`);
48
- this.log('');
49
- this.log(` Run ${styling_1.colors.highlight('dcd live <command> --help')} for details`);
50
- return;
51
- }
52
- const apiKey = apiKeyFlag || process.env.DEVICE_CLOUD_API_KEY;
53
- if (!apiKey) {
54
- this.error('API key is required. Provide via --api-key flag or DEVICE_CLOUD_API_KEY environment variable.');
55
- }
56
- switch (subcommand) {
57
- case 'start': {
58
- await this.startSession(apiUrl, apiKey, platform, binaryId);
59
- break;
60
- }
61
- case 'install': {
62
- if (!sessionId)
63
- this.error('--session-id is required for install');
64
- if (!binaryId)
65
- this.error('--app-binary-id is required for install');
66
- await this.installBinary(apiUrl, apiKey, sessionId, binaryId);
67
- break;
68
- }
69
- case 'exec': {
70
- if (!sessionId)
71
- this.error('--session-id is required for exec');
72
- if (!yaml)
73
- this.error('--yaml is required for exec');
74
- await this.execTest(apiUrl, apiKey, sessionId, yaml);
75
- break;
76
- }
77
- case 'stop': {
78
- if (!sessionId)
79
- this.error('--session-id is required for stop');
80
- await this.stopSession(apiUrl, apiKey, sessionId);
81
- break;
82
- }
83
- case 'status': {
84
- if (!sessionId)
85
- this.error('--session-id is required for status');
86
- await this.getStatus(apiUrl, apiKey, sessionId);
87
- break;
88
- }
89
- default: {
90
- break;
91
- }
92
- }
93
- }
94
- async execTest(apiUrl, apiKey, sessionId, yaml) {
95
- this.log(`${styling_1.symbols.running} Executing commands on session ${sessionId}...`);
96
- const res = await fetch(`${apiUrl}/live/${sessionId}/exec`, {
97
- body: JSON.stringify({ yaml }),
98
- headers: {
99
- 'content-type': 'application/json',
100
- 'x-app-api-key': apiKey,
101
- },
102
- method: 'POST',
103
- });
104
- if (!res.ok) {
105
- await api_gateway_1.ApiGateway.handleApiError(res, 'Failed to execute test');
106
- }
107
- const result = (await res.json());
108
- if (result.success) {
109
- this.log(`${styling_1.symbols.success} Command executed successfully`);
110
- }
111
- else {
112
- this.log(`${styling_1.symbols.error} Command failed`);
113
- }
114
- if (result.output) {
115
- this.log((0, styling_1.sectionHeader)('Output'));
116
- this.log(result.output);
117
- }
118
- if (result.error) {
119
- this.log((0, styling_1.sectionHeader)('Error'));
120
- this.log(styling_1.colors.error(result.error));
121
- }
122
- }
123
- getFrontendUrl(apiUrl) {
124
- if (apiUrl.includes('localhost:8000'))
125
- return 'http://localhost:5173';
126
- if (apiUrl.includes('api.dev.'))
127
- return 'https://dev.console.devicecloud.dev';
128
- return 'https://console.devicecloud.dev';
129
- }
130
- async getStatus(apiUrl, apiKey, sessionId) {
131
- const res = await fetch(`${apiUrl}/live/${sessionId}`, {
132
- headers: {
133
- 'x-app-api-key': apiKey,
134
- },
135
- method: 'GET',
136
- });
137
- if (!res.ok) {
138
- await api_gateway_1.ApiGateway.handleApiError(res, 'Failed to get session status');
139
- }
140
- const session = (await res.json());
141
- this.log((0, styling_1.sectionHeader)('Live Session'));
142
- this.log(` ${styling_1.colors.dim('Session ID:')} ${styling_1.colors.highlight(String(session.id))}`);
143
- this.log(` ${styling_1.colors.dim('Platform:')} ${session.platform}`);
144
- this.log(` ${styling_1.colors.dim('Status:')} ${session.status}`);
145
- if (session.binary_upload_id) {
146
- this.log(` ${styling_1.colors.dim('Binary:')} ${session.binary_upload_id}`);
147
- }
148
- this.log(` ${styling_1.colors.dim('Created:')} ${new Date(session.created_at).toLocaleString()}`);
149
- }
150
- async installBinary(apiUrl, apiKey, sessionId, binaryId) {
151
- this.log(`${styling_1.symbols.running} Installing binary ${styling_1.colors.highlight(binaryId)} on session ${sessionId}...`);
152
- const res = await fetch(`${apiUrl}/live/${sessionId}/install`, {
153
- body: JSON.stringify({ binaryUploadId: binaryId }),
154
- headers: {
155
- 'content-type': 'application/json',
156
- 'x-app-api-key': apiKey,
157
- },
158
- method: 'POST',
159
- });
160
- if (!res.ok) {
161
- await api_gateway_1.ApiGateway.handleApiError(res, 'Failed to install binary');
162
- }
163
- this.log(`${styling_1.symbols.success} Binary installed successfully`);
164
- }
165
- async startSession(apiUrl, apiKey, platform, binaryId) {
166
- this.log(`${styling_1.symbols.running} Starting ${platform} live session...`);
167
- const res = await fetch(`${apiUrl}/live`, {
168
- body: JSON.stringify({
169
- binaryUploadId: binaryId,
170
- platform,
171
- }),
172
- headers: {
173
- 'content-type': 'application/json',
174
- 'x-app-api-key': apiKey,
175
- },
176
- method: 'POST',
177
- });
178
- if (!res.ok) {
179
- await api_gateway_1.ApiGateway.handleApiError(res, 'Failed to start live session');
180
- }
181
- const session = (await res.json());
182
- const frontendUrl = this.getFrontendUrl(apiUrl);
183
- this.log(`${styling_1.symbols.success} Live session started`);
184
- this.log(` ${styling_1.colors.dim('Session ID:')} ${styling_1.colors.highlight(String(session.id))}`);
185
- this.log(` ${styling_1.colors.dim('Platform:')} ${session.platform}`);
186
- this.log(` ${styling_1.colors.dim('Status:')} ${session.status}`);
187
- this.log(` ${styling_1.colors.dim('Console:')} ${styling_1.colors.highlight(`${frontendUrl}/live?session=${session.id}`)}`);
188
- this.log('');
189
- this.log(` ${styling_1.colors.dim('Install a binary:')} ${styling_1.colors.highlight(`dcd live install --session-id ${session.id} --app-binary-id <id>`)}`);
190
- this.log(` ${styling_1.colors.dim('Run a command:')} ${styling_1.colors.highlight(`dcd live exec --session-id ${session.id} --yaml "- launchApp"`)}`);
191
- this.log(` ${styling_1.colors.dim('Stop session:')} ${styling_1.colors.highlight(`dcd live stop --session-id ${session.id}`)}`);
192
- }
193
- async stopSession(apiUrl, apiKey, sessionId) {
194
- this.log(`${styling_1.symbols.running} Stopping session ${sessionId}...`);
195
- const res = await fetch(`${apiUrl}/live/${sessionId}`, {
196
- headers: {
197
- 'x-app-api-key': apiKey,
198
- },
199
- method: 'DELETE',
200
- });
201
- if (!res.ok) {
202
- await api_gateway_1.ApiGateway.handleApiError(res, 'Failed to stop session');
203
- }
204
- this.log(`${styling_1.symbols.success} Session stopped`);
205
- }
206
- }
207
- exports.default = Live;