runcloud 0.1.91 → 0.1.92

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 CHANGED
@@ -28,6 +28,7 @@ curl -fsSL https://run.cloud/install | sh
28
28
 
29
29
  ```bash
30
30
  runcloud login # sign in with email, Google, or GitHub; stores a token in ~/.run-cloud/credentials
31
+ runcloud whoami # show the stored credential: account, API, expiry, file
31
32
  runcloud logout # delete the stored credential
32
33
  runcloud account # show your entitlement and metered balance
33
34
  ```
@@ -37,6 +38,23 @@ show a short code to confirm, so login works over SSH and on headless machines t
37
38
  pick with `--email`, `--google`, `--github`, or `--browser` to skip the prompt.
38
39
 
39
40
  The token expires — re-run `runcloud login` when a command reports you're logged out.
41
+ Logging in while a valid session exists reports that session and offers to keep it,
42
+ so running it out of habit no longer replaces a working credential.
43
+
44
+ `runcloud whoami` answers which credential is in play without calling the API, and
45
+ exits non-zero when there is none or it has expired:
46
+
47
+ ```
48
+ Account you@example.com
49
+ API https://api.run.cloud
50
+ Expires never
51
+ Credential ~/.run-cloud/credentials
52
+ ```
53
+
54
+ It reports whatever would actually be sent, including a credential supplied through
55
+ `RUN_CLOUD_API_KEY`, which takes precedence over the saved file. The account line is
56
+ only filled in when the sign-in method revealed an address — email sign-in does, the
57
+ browser and device handoffs do not.
40
58
 
41
59
  ## Remote simulators
42
60
 
@@ -3,7 +3,7 @@ import crypto from 'node:crypto';
3
3
  import { hostname } from 'node:os';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { ApiClient, ApiError } from '../api.js';
6
- import { clearCredentials, credentialsDisplayPath, loadCredentials, normalizeApiUrl, saveCredentials, } from '../config.js';
6
+ import { clearCredentials, credentialsDisplayPath, loadCredentials, loginCommandName, normalizeApiUrl, saveCredentials, } from '../config.js';
7
7
  import { acquirePromptIO, ask, PromptAbortedError, select, } from '../prompt.js';
8
8
  import { AuthError, createApiKey, fetchProviders, isValidEmail, isValidOtp, normalizeOtp, sendEmailCode, verifyEmailCode, } from '../runCloudAuth.js';
9
9
  const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
@@ -215,12 +215,25 @@ export async function revokeRunCloudCredential(apiUrl, token) {
215
215
  'revoke it from the run.cloud dashboard.');
216
216
  }
217
217
  }
218
+ function expiresAtLabel(creds) {
219
+ if (creds.expiresAt >= Number.MAX_SAFE_INTEGER)
220
+ return null;
221
+ return new Date(creds.expiresAt * 1000).toLocaleString();
222
+ }
218
223
  export function existingLoginSummary(creds) {
219
224
  const who = creds.account ? ` as ${creds.account}` : '';
220
- const expiry = creds.expiresAt < Number.MAX_SAFE_INTEGER
221
- ? `, valid until ${new Date(creds.expiresAt * 1000).toLocaleString()}`
222
- : '';
223
- return `You are already logged in${who} (${creds.apiUrl}${expiry}).`;
225
+ const expires = expiresAtLabel(creds);
226
+ return `You are already logged in${who} (${creds.apiUrl}${expires ? `, valid until ${expires}` : ''}).`;
227
+ }
228
+ export function whoamiReport(creds) {
229
+ const rows = [
230
+ ['Account', creds.account ?? 'not recorded (browser sign-in never sees an address)'],
231
+ ['API', creds.apiUrl],
232
+ ['Expires', expiresAtLabel(creds) ?? 'never'],
233
+ ['Credential', credentialsDisplayPath()],
234
+ ];
235
+ const width = Math.max(...rows.map(([label]) => label.length));
236
+ return rows.map(([label, value]) => `${label.padEnd(width + 2)}${value}`).join('\n');
224
237
  }
225
238
  export async function confirmReplaceExistingLogin(creds) {
226
239
  if (!creds)
@@ -404,6 +417,20 @@ export function registerLogin(program) {
404
417
  process.exitCode = 1;
405
418
  }
406
419
  });
420
+ program
421
+ .command('whoami')
422
+ .description(isRunCloud
423
+ ? 'Show which run.cloud account this machine is signed in as'
424
+ : 'Show which Newly account this machine is signed in as')
425
+ .action(() => {
426
+ const creds = loadCredentials();
427
+ if (!creds) {
428
+ console.error(`Not logged in. Run \`${loginCommandName()}\`.`);
429
+ process.exitCode = 1;
430
+ return;
431
+ }
432
+ console.log(whoamiReport(creds));
433
+ });
407
434
  program
408
435
  .command('logout')
409
436
  .description(isRunCloud
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.1.91';
1
+ export const CLI_VERSION = '0.1.92';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.1.91",
3
+ "version": "0.1.92",
4
4
  "description": "Create and control run.cloud remote mobile simulators and cloud sandboxes",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [