(opts: CommonOptions, deps: AuthDeps = {})
| 182 | } |
| 183 | |
| 184 | export async function runWhoami(opts: CommonOptions, deps: AuthDeps = {}): Promise<MeResponse> { |
| 185 | const out = makeOutput(opts.output, deps); |
| 186 | const env = deps.env ?? process.env; |
| 187 | |
| 188 | // Resolve the endpoint URL so it can be surfaced in text output. |
| 189 | // Dry-run uses the flag/env/default chain without touching credentials. |
| 190 | // Real path uses the same loadConfig the HttpClient factory uses so the |
| 191 | // displayed URL always matches where requests actually go (dogfood L1788). |
| 192 | let resolvedEndpoint: string; |
| 193 | if (opts.dryRun) { |
| 194 | resolvedEndpoint = opts.endpointUrl ?? env.TESTSPRITE_API_URL ?? 'https://api.testsprite.com'; |
| 195 | } else { |
| 196 | const credentialsPath = deps.credentialsPath ?? defaultCredentialsPath(); |
| 197 | const config = loadConfig({ |
| 198 | profile: opts.profile, |
| 199 | endpointUrl: opts.endpointUrl, |
| 200 | env, |
| 201 | credentialsPath, |
| 202 | }); |
| 203 | resolvedEndpoint = config.apiUrl; |
| 204 | } |
| 205 | |
| 206 | // Dry-run + real path both go through the shared factory. |
| 207 | const client = makeHttpClient(opts, { |
| 208 | env: deps.env, |
| 209 | credentialsPath: deps.credentialsPath, |
| 210 | fetchImpl: deps.fetchImpl, |
| 211 | stderr: deps.stderr, |
| 212 | }); |
| 213 | |
| 214 | const me = await client.get<MeResponse>('/me'); |
| 215 | out.print(me, data => { |
| 216 | const m = data as MeResponse; |
| 217 | const lines = [ |
| 218 | `userId: ${m.userId}`, |
| 219 | // Human-readable identity, rendered only when the backend supplies it |
| 220 | // (dogfood L1866) — confirm the account at a glance before a billable run. |
| 221 | ...(m.displayName ? [`name: ${m.displayName}`] : []), |
| 222 | ...(m.email ? [`email: ${m.email}`] : []), |
| 223 | `keyId: ${m.keyId}`, |
| 224 | // Show the resolved endpoint so the user knows which env they are bound to |
| 225 | // without having to infer from the `env` field alone (dogfood L1788). |
| 226 | `endpoint: ${resolvedEndpoint}`, |
| 227 | `env: ${m.env}`, |
| 228 | `scopes: ${m.scopes.join(', ')}`, |
| 229 | ]; |
| 230 | // C2: warn in text mode when key cannot write/run |
| 231 | const missingScopes = (['write:tests', 'run:tests'] as const).filter( |
| 232 | s => !m.scopes.includes(s), |
| 233 | ); |
| 234 | if (missingScopes.length > 0) { |
| 235 | lines.push( |
| 236 | `note: this key cannot run write or test-trigger commands. Missing scopes: ${missingScopes.join(', ')}. Ask your account owner to extend it via the portal.`, |
| 237 | ); |
| 238 | } |
| 239 | return lines.join('\n'); |
| 240 | }); |
| 241 | return me; |
no test coverage detected