@@ -3,13 +3,15 @@ import * as os from "os";
33import * as path from "path" ;
44
55import chalk from "chalk" ;
6- // Polyfill fetch for Node < 18
76import nodeFetch from "node-fetch" ;
87import open from "open" ;
98
9+ import { logger } from "src/util/logger.js" ;
10+
1011import { getApiClient } from "../config.js" ;
1112// eslint-disable-next-line import/order
1213import { env } from "../env.js" ;
14+
1315if ( ! globalThis . fetch ) {
1416 globalThis . fetch = nodeFetch as unknown as typeof globalThis . fetch ;
1517}
@@ -21,33 +23,6 @@ function getAuthConfigPath() {
2123 return path . join ( continueHome , "auth.json" ) ;
2224}
2325
24- // Represents an authenticated user's configuration
25- export interface AuthenticatedConfig {
26- userId : string ;
27- userEmail : string ;
28- accessToken : string ;
29- refreshToken : string ;
30- expiresAt : number ;
31- organizationId : string | null | undefined ; // null means personal organization, undefined triggers auto-selection
32- configUri ?: string ; // Optional config URI (file:// or slug://owner/slug)
33- modelName ?: string ; // Name of the selected model
34- }
35-
36- // Represents configuration when using environment variable auth
37- export interface EnvironmentAuthConfig {
38- /**
39- * This userId?: undefined; field a trick to help TypeScript differentiate between
40- * AuthenticatedConfig and EnvironmentAuthConfig. Otherwise AuthenticatedConfig is
41- * a possible subtype of EnvironmentAuthConfig and TypeScript gets confused where
42- * type guards are involved.
43- */
44- userId ?: undefined ;
45- accessToken : string ;
46- organizationId : string | null ; // Can be set via --org flag in headless mode
47- configUri ?: string ; // Optional config URI (file:// or slug://owner/slug)
48- modelName ?: string ; // Name of the selected model
49- }
50-
5126// Union type representing the possible authentication states
5227export type AuthConfig = AuthenticatedConfig | EnvironmentAuthConfig | null ;
5328
@@ -117,6 +92,11 @@ import {
11792
11893import { autoSelectOrganizationAndConfig } from "./orgSelection.js" ;
11994import { pathToUri , slugToUri , uriToPath , uriToSlug } from "./uriUtils.js" ;
95+ import {
96+ AuthenticatedConfig ,
97+ DeviceAuthorizationResponse ,
98+ EnvironmentAuthConfig ,
99+ } from "./workos-types.js" ;
120100import {
121101 handleCliOrgForAuthenticatedConfig ,
122102 handleCliOrgForEnvironmentAuth ,
@@ -266,46 +246,30 @@ export function updateLocalConfigPath(localConfigPath: string | null): void {
266246/**
267247 * Checks if the user is authenticated and the token is valid
268248 */
269- export function isAuthenticated ( ) : boolean {
249+ export async function isAuthenticated ( ) : Promise < boolean > {
270250 const config = loadAuthConfig ( ) ;
271251
272252 if ( config === null ) {
273253 return false ;
274254 }
275255
276- // Environment auth is always valid
277256 if ( isEnvironmentAuthConfig ( config ) ) {
278257 return true ;
279258 }
280259
281- /**
282- * THIS CODE DOESN'T WORK.
283- * .catch() will never return in a non-async function.
284- * It's a hallucination.
285- **/
286260 if ( Date . now ( ) > config . expiresAt ) {
287- // Try refreshing the token
288- refreshToken ( config . refreshToken ) . catch ( ( ) => {
289- // If refresh fails, we're not authenticated
261+ try {
262+ const refreshed = await refreshToken ( config . refreshToken ) ;
263+ return isAuthenticatedConfig ( refreshed ) ;
264+ } catch ( e ) {
265+ logger . error ( "Failed to refresh auto token" , e ) ;
290266 return false ;
291- } ) ;
267+ }
292268 }
293269
294270 return true ;
295271}
296272
297- /**
298- * Device authorization response from WorkOS
299- */
300- interface DeviceAuthorizationResponse {
301- device_code : string ;
302- user_code : string ;
303- verification_uri : string ;
304- verification_uri_complete : string ;
305- expires_in : number ;
306- interval : number ;
307- }
308-
309273/**
310274 * Request device authorization from WorkOS
311275 */
0 commit comments