@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.
- package/README.md +40 -2
- package/dist/commands/artifacts.d.ts +47 -18
- package/dist/commands/artifacts.js +68 -60
- package/dist/commands/cloud.d.ts +228 -88
- package/dist/commands/cloud.js +389 -288
- package/dist/commands/list.d.ts +39 -38
- package/dist/commands/list.js +122 -127
- package/dist/commands/live.d.ts +2 -0
- package/dist/commands/live.js +513 -0
- package/dist/commands/login.d.ts +17 -0
- package/dist/commands/login.js +250 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.js +32 -0
- package/dist/commands/status.d.ts +23 -42
- package/dist/commands/status.js +162 -173
- package/dist/commands/switch-org.d.ts +12 -0
- package/dist/commands/switch-org.js +78 -0
- package/dist/commands/upgrade.d.ts +2 -0
- package/dist/commands/upgrade.js +122 -0
- package/dist/commands/upload.d.ts +33 -18
- package/dist/commands/upload.js +62 -67
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +34 -0
- package/dist/config/environments.d.ts +31 -0
- package/dist/config/environments.js +58 -0
- package/dist/config/flags/api.flags.d.ts +10 -2
- package/dist/config/flags/api.flags.js +12 -10
- package/dist/config/flags/binary.flags.d.ts +17 -4
- package/dist/config/flags/binary.flags.js +13 -14
- package/dist/config/flags/device.flags.d.ts +49 -11
- package/dist/config/flags/device.flags.js +41 -33
- package/dist/config/flags/environment.flags.d.ts +27 -6
- package/dist/config/flags/environment.flags.js +23 -25
- package/dist/config/flags/execution.flags.d.ts +35 -8
- package/dist/config/flags/execution.flags.js +30 -37
- package/dist/config/flags/github.flags.d.ts +23 -5
- package/dist/config/flags/github.flags.js +18 -11
- package/dist/config/flags/output.flags.d.ts +57 -13
- package/dist/config/flags/output.flags.js +47 -43
- package/dist/constants.d.ts +218 -51
- package/dist/constants.js +2 -2
- package/dist/gateways/api-gateway.d.ts +43 -12
- package/dist/gateways/api-gateway.js +240 -100
- package/dist/gateways/cli-auth-gateway.d.ts +13 -0
- package/dist/gateways/cli-auth-gateway.js +57 -0
- package/dist/gateways/supabase-gateway.d.ts +11 -11
- package/dist/gateways/supabase-gateway.js +15 -39
- package/dist/index.d.ts +2 -1
- package/dist/index.js +93 -2
- package/dist/methods.d.ts +3 -5
- package/dist/methods.js +170 -178
- package/dist/services/device-validation.service.d.ts +8 -0
- package/dist/services/device-validation.service.js +55 -35
- package/dist/services/execution-plan.service.js +27 -15
- package/dist/services/execution-plan.utils.d.ts +3 -0
- package/dist/services/execution-plan.utils.js +10 -32
- package/dist/services/metadata-extractor.service.d.ts +0 -2
- package/dist/services/metadata-extractor.service.js +57 -57
- package/dist/services/moropo.service.js +25 -24
- package/dist/services/report-download.service.d.ts +12 -1
- package/dist/services/report-download.service.js +31 -20
- package/dist/services/results-polling.service.d.ts +6 -7
- package/dist/services/results-polling.service.js +80 -33
- package/dist/services/telemetry.service.d.ts +40 -0
- package/dist/services/telemetry.service.js +230 -0
- package/dist/services/test-submission.service.js +2 -1
- package/dist/services/version.service.d.ts +3 -2
- package/dist/services/version.service.js +27 -11
- package/dist/types/domain/auth.types.d.ts +12 -0
- package/dist/types/{schema.types.js → domain/auth.types.js} +0 -1
- package/dist/types/domain/live.types.d.ts +76 -0
- package/dist/types/domain/live.types.js +4 -0
- package/dist/utils/auth.d.ts +13 -0
- package/dist/utils/auth.js +142 -0
- package/dist/utils/cli.d.ts +35 -0
- package/dist/utils/cli.js +127 -0
- package/dist/utils/compatibility.d.ts +2 -1
- package/dist/utils/compatibility.js +2 -2
- package/dist/utils/config-store.d.ts +35 -0
- package/dist/utils/config-store.js +125 -0
- package/dist/utils/connectivity.js +7 -3
- package/dist/utils/expo.js +14 -3
- package/dist/utils/orgs.d.ts +11 -0
- package/dist/utils/orgs.js +40 -0
- package/dist/utils/paths.d.ts +11 -0
- package/dist/utils/paths.js +24 -0
- package/dist/utils/progress.d.ts +13 -0
- package/dist/utils/progress.js +50 -0
- package/dist/utils/styling.d.ts +13 -5
- package/dist/utils/styling.js +37 -7
- package/package.json +26 -38
- package/bin/dev.cmd +0 -3
- package/bin/dev.js +0 -6
- package/bin/run.cmd +0 -3
- package/bin/run.js +0 -7
- package/dist/types/schema.types.d.ts +0 -2702
- package/oclif.manifest.json +0 -884
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loginCommand = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `dcd login` — delegates auth to the web frontend and persists the resulting
|
|
6
|
+
* Supabase session locally.
|
|
7
|
+
*
|
|
8
|
+
* Flow (PKCE S256, no loopback):
|
|
9
|
+
* 1. CLI mints:
|
|
10
|
+
* - `state`: 32 random bytes, hex
|
|
11
|
+
* - `code_verifier`:32 random bytes, base64url
|
|
12
|
+
* - `code_challenge` = base64url(sha256(code_verifier))
|
|
13
|
+
* 2. CLI opens <frontend>/cli-login?state=...&code_challenge=... in the browser.
|
|
14
|
+
* 3. User signs in (OTP or SSO) and explicitly authorizes the handoff on
|
|
15
|
+
* the frontend.
|
|
16
|
+
* 4. Frontend POSTs {state, code_challenge, session...} to the dcd api at
|
|
17
|
+
* POST /cli-login/handoff. The api stores a short-TTL row keyed by state.
|
|
18
|
+
* 5. Meanwhile, the CLI polls POST /cli-login/claim with {state, code_verifier}.
|
|
19
|
+
* Once the api has the row, it verifies sha256(verifier) === challenge,
|
|
20
|
+
* deletes the row, and returns the session.
|
|
21
|
+
* 6. CLI fetches /me/orgs with the fresh Bearer token and prompts the user to
|
|
22
|
+
* pick an org. Org selection lives here, not in the web UI — that way the
|
|
23
|
+
* CLI login and `dcd switch-org` share one picker.
|
|
24
|
+
*
|
|
25
|
+
* Why PKCE + server rendezvous (instead of a localhost loopback): Safari
|
|
26
|
+
* blocks HTTPS → HTTP fetches to 127.0.0.1 as mixed content, and a loopback
|
|
27
|
+
* flow can't work at all over SSH / "open this URL on your phone". The
|
|
28
|
+
* rendezvous endpoint makes both cases trivial. A leaked URL is inert: it
|
|
29
|
+
* carries the challenge, not the verifier.
|
|
30
|
+
*/
|
|
31
|
+
const p = require("@clack/prompts");
|
|
32
|
+
const citty_1 = require("citty");
|
|
33
|
+
const node_child_process_1 = require("node:child_process");
|
|
34
|
+
const node_crypto_1 = require("node:crypto");
|
|
35
|
+
const environments_1 = require("../config/environments");
|
|
36
|
+
const cli_1 = require("../utils/cli");
|
|
37
|
+
const config_store_1 = require("../utils/config-store");
|
|
38
|
+
const orgs_1 = require("../utils/orgs");
|
|
39
|
+
const styling_1 = require("../utils/styling");
|
|
40
|
+
const LOGIN_TIMEOUT_MS = 10 * 60 * 1000;
|
|
41
|
+
// 1s feels snappy after the user clicks "Authorize" in the browser. The api
|
|
42
|
+
// rate-limits /cli-login/claim at 60/min which is exactly this cadence.
|
|
43
|
+
const POLL_INTERVAL_MS = 1000;
|
|
44
|
+
exports.loginCommand = (0, citty_1.defineCommand)({
|
|
45
|
+
meta: {
|
|
46
|
+
name: 'login',
|
|
47
|
+
description: 'Authenticate with devicecloud.dev via your browser',
|
|
48
|
+
},
|
|
49
|
+
args: {
|
|
50
|
+
'api-url': {
|
|
51
|
+
type: 'string',
|
|
52
|
+
default: 'https://api.devicecloud.dev',
|
|
53
|
+
description: 'API base URL',
|
|
54
|
+
},
|
|
55
|
+
'frontend-url': {
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: 'Override the frontend URL used to complete login (defaults per env)',
|
|
58
|
+
},
|
|
59
|
+
// citty treats `--no-<flag>` as negating `<flag>`, so the flag has to be
|
|
60
|
+
// named `browser` (defaulting true) for `--no-browser` to set it false.
|
|
61
|
+
browser: {
|
|
62
|
+
type: 'boolean',
|
|
63
|
+
default: true,
|
|
64
|
+
description: 'Open the login URL in a browser (pass --no-browser to just print it)',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
async run({ args }) {
|
|
68
|
+
const apiUrl = args['api-url'].replace(/\/$/, '');
|
|
69
|
+
const frontendOverride = args['frontend-url'];
|
|
70
|
+
const noBrowser = args.browser === false;
|
|
71
|
+
// If there's an existing stored session, make the user confirm before we
|
|
72
|
+
// overwrite it. Silent clobber is fine for power users but surprising if
|
|
73
|
+
// someone runs `dcd login` by mistake while already authenticated.
|
|
74
|
+
const existing = (0, config_store_1.readConfig)();
|
|
75
|
+
if (existing?.session) {
|
|
76
|
+
const currentOrg = existing.current_org_name ?? existing.current_org_id;
|
|
77
|
+
const ok = await p.confirm({
|
|
78
|
+
message: `Already logged in as ${existing.session.user_email}` +
|
|
79
|
+
(currentOrg ? ` (org ${currentOrg})` : '') +
|
|
80
|
+
`. Sign out and log in again?`,
|
|
81
|
+
initialValue: false,
|
|
82
|
+
});
|
|
83
|
+
if (p.isCancel(ok) || !ok) {
|
|
84
|
+
cli_1.logger.log(`${styling_1.symbols.info} Keeping existing session.`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const env = (0, environments_1.inferEnvFromApiUrl)(apiUrl);
|
|
89
|
+
const SUPABASE_URL = environments_1.ENVIRONMENTS[env].supabase.url;
|
|
90
|
+
const frontendUrl = (frontendOverride ?? (0, environments_1.resolveFrontendUrl)(apiUrl)).replace(/\/$/, '');
|
|
91
|
+
const state = (0, node_crypto_1.randomBytes)(32).toString('hex');
|
|
92
|
+
const codeVerifier = base64url((0, node_crypto_1.randomBytes)(32));
|
|
93
|
+
const codeChallenge = base64url((0, node_crypto_1.createHash)('sha256').update(codeVerifier, 'ascii').digest());
|
|
94
|
+
const loginUrl = `${frontendUrl}/cli-login?state=${state}&code_challenge=${codeChallenge}`;
|
|
95
|
+
cli_1.logger.log((0, styling_1.sectionHeader)('Signing in to devicecloud.dev'));
|
|
96
|
+
if (noBrowser) {
|
|
97
|
+
cli_1.logger.log(` ${styling_1.colors.dim('Open this URL in a browser to finish login:')}`);
|
|
98
|
+
cli_1.logger.log(` ${styling_1.colors.highlight(loginUrl)}`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
cli_1.logger.log(` ${styling_1.colors.dim('Opening your browser...')}`);
|
|
102
|
+
const opened = openBrowser(loginUrl);
|
|
103
|
+
if (!opened) {
|
|
104
|
+
cli_1.logger.log(` ${styling_1.colors.dim('Could not launch a browser. Open this URL manually:')}`);
|
|
105
|
+
cli_1.logger.log(` ${styling_1.colors.highlight(loginUrl)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
cli_1.logger.log(` ${styling_1.colors.dim('Waiting for login to complete...')}\n`);
|
|
109
|
+
try {
|
|
110
|
+
const payload = await pollForClaim(apiUrl, state, codeVerifier);
|
|
111
|
+
if (!payload.access_token || typeof payload.access_token !== 'string') {
|
|
112
|
+
throw new cli_1.CliError('Claim response did not include an access_token.');
|
|
113
|
+
}
|
|
114
|
+
// Fetch orgs with the just-minted Bearer token. We don't write the
|
|
115
|
+
// config until the user has picked an org — half-completed state isn't
|
|
116
|
+
// useful and the handoff row is already single-use consumed.
|
|
117
|
+
const bearerHeaders = {
|
|
118
|
+
authorization: `Bearer ${payload.access_token}`,
|
|
119
|
+
};
|
|
120
|
+
let orgs;
|
|
121
|
+
try {
|
|
122
|
+
orgs = await (0, orgs_1.fetchOrgs)(apiUrl, bearerHeaders);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
// The api rejected the JWT. Before blaming the api, hit Supabase's
|
|
126
|
+
// own /auth/v1/user directly with the same token — if Supabase also
|
|
127
|
+
// rejects it, the token itself is bad; if Supabase accepts, the
|
|
128
|
+
// api's JwtService is misconfigured.
|
|
129
|
+
const iss = decodeJwtIssuer(payload.access_token);
|
|
130
|
+
const supabaseUser = await probeSupabaseUser(iss, environments_1.ENVIRONMENTS[env].supabase.anonKey, payload.access_token);
|
|
131
|
+
const parts = [
|
|
132
|
+
iss ? `token iss: ${iss}` : null,
|
|
133
|
+
`supabase /auth/v1/user: ${supabaseUser}`,
|
|
134
|
+
].filter(Boolean);
|
|
135
|
+
throw new cli_1.CliError(`${err.message} [${parts.join(' | ')}]`);
|
|
136
|
+
}
|
|
137
|
+
const chosen = await (0, orgs_1.pickOrg)(orgs);
|
|
138
|
+
(0, config_store_1.writeConfig)({
|
|
139
|
+
version: 1,
|
|
140
|
+
env,
|
|
141
|
+
api_url: apiUrl,
|
|
142
|
+
supabase_url: SUPABASE_URL,
|
|
143
|
+
session: {
|
|
144
|
+
access_token: payload.access_token,
|
|
145
|
+
refresh_token: payload.refresh_token,
|
|
146
|
+
expires_at: payload.expires_at,
|
|
147
|
+
user_email: payload.user_email,
|
|
148
|
+
user_id: payload.user_id,
|
|
149
|
+
},
|
|
150
|
+
current_org_id: chosen.id,
|
|
151
|
+
current_org_name: chosen.name,
|
|
152
|
+
});
|
|
153
|
+
cli_1.logger.log(`${styling_1.symbols.success} ${styling_1.colors.bold('Logged in')} as ${styling_1.colors.highlight(payload.user_email)}`);
|
|
154
|
+
cli_1.logger.log(` ${styling_1.colors.dim('Organization:')} ${styling_1.colors.highlight(chosen.name)}`);
|
|
155
|
+
if (orgs.length > 1) {
|
|
156
|
+
cli_1.logger.log(` ${styling_1.colors.dim('Switch orgs later with')} ${styling_1.colors.highlight('dcd switch-org')}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
cli_1.logger.error(error, { exit: 1 });
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
function openBrowser(url) {
|
|
165
|
+
const cmd = process.platform === 'darwin'
|
|
166
|
+
? { bin: 'open', args: [url] }
|
|
167
|
+
: process.platform === 'win32'
|
|
168
|
+
? { bin: 'cmd', args: ['/c', 'start', '""', url] }
|
|
169
|
+
: { bin: 'xdg-open', args: [url] };
|
|
170
|
+
try {
|
|
171
|
+
const child = (0, node_child_process_1.spawn)(cmd.bin, cmd.args, { detached: true, stdio: 'ignore' });
|
|
172
|
+
child.unref();
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async function pollForClaim(apiUrl, state, codeVerifier) {
|
|
180
|
+
const claimUrl = `${apiUrl}/cli-login/claim`;
|
|
181
|
+
const deadline = Date.now() + LOGIN_TIMEOUT_MS;
|
|
182
|
+
while (Date.now() < deadline) {
|
|
183
|
+
let res;
|
|
184
|
+
try {
|
|
185
|
+
res = await fetch(claimUrl, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers: { 'content-type': 'application/json' },
|
|
188
|
+
body: JSON.stringify({ state, code_verifier: codeVerifier }),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Network blip — don't kill the login, just back off and try again.
|
|
193
|
+
await sleep(POLL_INTERVAL_MS);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (res.ok) {
|
|
197
|
+
return (await res.json());
|
|
198
|
+
}
|
|
199
|
+
if (res.status === 404) {
|
|
200
|
+
// Not yet handed off (or already claimed elsewhere, or expired).
|
|
201
|
+
await sleep(POLL_INTERVAL_MS);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (res.status === 429) {
|
|
205
|
+
// Polled too fast — back off more aggressively before retrying.
|
|
206
|
+
await sleep(POLL_INTERVAL_MS * 3);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const body = await res.text().catch(() => '');
|
|
210
|
+
throw new cli_1.CliError(`Login failed: ${res.status} ${res.statusText}${body ? ` — ${body}` : ''}`);
|
|
211
|
+
}
|
|
212
|
+
throw new cli_1.CliError('Login timed out. Please run `dcd login` again.');
|
|
213
|
+
}
|
|
214
|
+
function base64url(buf) {
|
|
215
|
+
return buf.toString('base64').replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '');
|
|
216
|
+
}
|
|
217
|
+
async function probeSupabaseUser(iss, anonKey, token) {
|
|
218
|
+
if (!iss)
|
|
219
|
+
return 'skipped (no iss)';
|
|
220
|
+
try {
|
|
221
|
+
const res = await fetch(`${iss}/user`, {
|
|
222
|
+
headers: {
|
|
223
|
+
authorization: `Bearer ${token}`,
|
|
224
|
+
apikey: anonKey,
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
const bodyText = await res.text().catch(() => '');
|
|
228
|
+
return `HTTP ${res.status}${bodyText ? ` — ${bodyText.slice(0, 200)}` : ''}`;
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
return `network error: ${err.message}`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function decodeJwtIssuer(token) {
|
|
235
|
+
try {
|
|
236
|
+
const [, payloadB64] = token.split('.');
|
|
237
|
+
if (!payloadB64)
|
|
238
|
+
return null;
|
|
239
|
+
const json = Buffer.from(payloadB64.replaceAll('-', '+').replaceAll('_', '/'), 'base64').toString('utf8');
|
|
240
|
+
const parsed = JSON.parse(json);
|
|
241
|
+
return parsed.iss ?? null;
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function sleep(ms) {
|
|
248
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
249
|
+
}
|
|
250
|
+
exports.default = exports.loginCommand;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logoutCommand = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `dcd logout` — clears the stored Supabase session and best-effort revokes
|
|
6
|
+
* it on Supabase. Leaves DEVICE_CLOUD_API_KEY (env/flag) untouched.
|
|
7
|
+
*/
|
|
8
|
+
const citty_1 = require("citty");
|
|
9
|
+
const environments_1 = require("../config/environments");
|
|
10
|
+
const cli_auth_gateway_1 = require("../gateways/cli-auth-gateway");
|
|
11
|
+
const cli_1 = require("../utils/cli");
|
|
12
|
+
const config_store_1 = require("../utils/config-store");
|
|
13
|
+
const styling_1 = require("../utils/styling");
|
|
14
|
+
exports.logoutCommand = (0, citty_1.defineCommand)({
|
|
15
|
+
meta: {
|
|
16
|
+
name: 'logout',
|
|
17
|
+
description: 'Clear the stored devicecloud.dev session',
|
|
18
|
+
},
|
|
19
|
+
async run() {
|
|
20
|
+
const config = (0, config_store_1.readConfig)();
|
|
21
|
+
if (!config?.session) {
|
|
22
|
+
cli_1.logger.log(`${styling_1.symbols.info} No active session found (${styling_1.colors.dim((0, config_store_1.getConfigPath)())}).`);
|
|
23
|
+
(0, config_store_1.clearConfig)();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const { anonKey } = environments_1.ENVIRONMENTS[config.env].supabase;
|
|
27
|
+
await cli_auth_gateway_1.CliAuthGateway.signOut(config.supabase_url, anonKey, config.session);
|
|
28
|
+
(0, config_store_1.clearConfig)();
|
|
29
|
+
cli_1.logger.log(`${styling_1.symbols.success} Logged out ${styling_1.colors.dim(`(${config.session.user_email})`)}.`);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
exports.default = exports.logoutCommand;
|
|
@@ -1,44 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
attempts?: number;
|
|
6
|
-
connectivityCheck?: {
|
|
7
|
-
connected: boolean;
|
|
8
|
-
endpointResults: ConnectivityCheckResult['endpointResults'];
|
|
9
|
-
message: string;
|
|
1
|
+
export declare const statusCommand: import("citty").CommandDef<{
|
|
2
|
+
json: {
|
|
3
|
+
type: "boolean";
|
|
4
|
+
description: string;
|
|
10
5
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
name?: string;
|
|
15
|
-
status: 'CANCELLED' | 'FAILED' | 'PASSED' | 'PENDING' | 'QUEUED' | 'RUNNING';
|
|
16
|
-
tests: {
|
|
17
|
-
createdAt?: string;
|
|
18
|
-
durationSeconds?: number;
|
|
19
|
-
failReason?: string;
|
|
20
|
-
name: string;
|
|
21
|
-
status: 'CANCELLED' | 'FAILED' | 'PASSED' | 'PENDING' | 'QUEUED' | 'RUNNING';
|
|
22
|
-
}[];
|
|
23
|
-
uploadId?: string;
|
|
24
|
-
};
|
|
25
|
-
export default class Status extends Command {
|
|
26
|
-
static description: string;
|
|
27
|
-
static enableJsonFlag: boolean;
|
|
28
|
-
static examples: string[];
|
|
29
|
-
static flags: {
|
|
30
|
-
apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
31
|
-
apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
32
|
-
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
33
|
-
name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
34
|
-
'upload-id': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
|
+
name: {
|
|
7
|
+
type: "string";
|
|
8
|
+
description: string;
|
|
35
9
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
10
|
+
'upload-id': {
|
|
11
|
+
type: "string";
|
|
12
|
+
description: string;
|
|
13
|
+
};
|
|
14
|
+
'api-key': {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly alias: ["apiKey"];
|
|
17
|
+
readonly description: "API key for devicecloud.dev (find this in the console UI). You can also set the DEVICE_CLOUD_API_KEY environment variable.";
|
|
18
|
+
};
|
|
19
|
+
'api-url': {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly alias: ["apiURL", "apiUrl"];
|
|
22
|
+
readonly description: "API base URL (defaults to the URL stored by `dcd login`, else prod)";
|
|
23
|
+
};
|
|
24
|
+
}>;
|
|
25
|
+
export default statusCommand;
|