@@ -40,6 +40,7 @@ import logger from '../lib/logger.js';
4040import { warn , success , print , note , textPrompt , confirmPrompt } from '../ui/index.js' ;
4141import { green , red , dim } from '../ui/colors.js' ;
4242import { SONARCLOUD_URL , SONARCLOUD_HOSTNAME } from '../lib/config-constants.js' ;
43+ import { InvalidOptionError } from './common/error' ;
4344
4445/**
4546 * Check if server is SonarCloud
@@ -191,6 +192,48 @@ async function validateOrSelectOrganization(
191192 return selectedOrg . trim ( ) ;
192193}
193194
195+ async function validateLoginOptions ( options : {
196+ server ?: string ;
197+ org ?: string ;
198+ withToken ?: string ;
199+ region ?: string ;
200+ } ) {
201+ if ( options . org !== undefined && ! options . org . trim ( ) ) {
202+ throw new InvalidOptionError (
203+ '--org value cannot be empty. Provide a valid organization key (e.g., --org my-org)' ,
204+ ) ;
205+ }
206+
207+ if ( options . withToken !== undefined && ! options . withToken . trim ( ) ) {
208+ throw new InvalidOptionError (
209+ '--with-token value cannot be empty. Provide a valid token or omit the flag for browser authentication' ,
210+ ) ;
211+ }
212+
213+ if ( options . server !== undefined && ! options . server . trim ( ) ) {
214+ throw new InvalidOptionError (
215+ '--server value cannot be empty. Provide a valid URL (e.g., https://sonarcloud.io)' ,
216+ ) ;
217+ }
218+
219+ let server = options . server ;
220+ if ( ! server ) {
221+ const configServer = await findServerInConfigs ( ) ;
222+ server = configServer || SONARCLOUD_URL ;
223+ }
224+
225+ if ( options . server !== undefined ) {
226+ try {
227+ new URL ( server ) ;
228+ } catch {
229+ throw new InvalidOptionError (
230+ `Invalid server URL: '${ server } '. Provide a valid URL (e.g., https://sonarcloud.io)` ,
231+ ) ;
232+ }
233+ }
234+ return server ;
235+ }
236+
194237/**
195238 * Login command - authenticate and save token with organization
196239 */
@@ -201,39 +244,7 @@ export async function authLoginCommand(options: {
201244 region ?: string ;
202245} ) : Promise < void > {
203246 await runCommand ( async ( ) => {
204- if ( options . org !== undefined && ! options . org . trim ( ) ) {
205- throw new Error (
206- '--org value cannot be empty. Provide a valid organization key (e.g., --org my-org)' ,
207- ) ;
208- }
209-
210- if ( options . withToken !== undefined && ! options . withToken . trim ( ) ) {
211- throw new Error (
212- '--with-token value cannot be empty. Provide a valid token or omit the flag for browser authentication' ,
213- ) ;
214- }
215-
216- if ( options . server !== undefined && ! options . server . trim ( ) ) {
217- throw new Error (
218- '--server value cannot be empty. Provide a valid URL (e.g., https://sonarcloud.io)' ,
219- ) ;
220- }
221-
222- let server = options . server ;
223- if ( ! server ) {
224- const configServer = await findServerInConfigs ( ) ;
225- server = configServer || SONARCLOUD_URL ;
226- }
227-
228- if ( options . server !== undefined ) {
229- try {
230- new URL ( server ) ;
231- } catch {
232- throw new Error (
233- `Invalid server URL: '${ server } '. Provide a valid URL (e.g., https://sonarcloud.io)` ,
234- ) ;
235- }
236- }
247+ const server = await validateLoginOptions ( options ) ;
237248
238249 const isCloud = isSonarCloud ( server ) ;
239250 const region = ( options . region || 'eu' ) as 'eu' | 'us' ;
@@ -265,12 +276,25 @@ export async function authLoginCommand(options: {
265276 const state = loadState ( ) ;
266277 const keystoreKey = generateConnectionId ( server , org ) ;
267278
268- addOrUpdateConnection ( state , server , isCloud ? 'cloud' : 'on-premise' , {
279+ const connection = addOrUpdateConnection ( state , server , isCloud ? 'cloud' : 'on-premise' , {
269280 orgKey : org ,
270281 region : isCloud ? region : undefined ,
271282 keystoreKey,
272283 } ) ;
273284
285+ // Fetch server-side IDs for telemetry enrichment (best effort, non-blocking on error).
286+ const actualToken = token || ( await getKeystoreToken ( server , org ) ) ;
287+ if ( actualToken ) {
288+ const apiClient = new SonarQubeClient ( server , actualToken ) ;
289+ connection . userUuid = ( await apiClient . getCurrentUser ( ) ) ?. id ?? null ;
290+ if ( isCloud && org ) {
291+ connection . organizationUuidV4 = await apiClient . getOrganizationId ( org ) ;
292+ } else if ( ! isCloud ) {
293+ const status = await apiClient . getSystemStatus ( ) ;
294+ connection . sqsInstallationId = status . id ?? null ;
295+ }
296+ }
297+
274298 saveState ( state ) ;
275299
276300 const displayServer = isSonarCloud ( server ) ? `${ server } (${ org } )` : server ;
0 commit comments