11import { readFileSync , writeFileSync , mkdirSync , existsSync , chmodSync } from 'node:fs' ;
22import { homedir } from 'node:os' ;
3- import { join } from 'node:path' ;
3+ import { dirname , join , resolve } from 'node:path' ;
44import type { TokenData , OAuthTokenResponse } from '../types/whoop.js' ;
55import { WhoopError , ExitCode } from '../utils/errors.js' ;
66
7- const CONFIG_DIR = join ( homedir ( ) , '.whoop-cli' ) ;
8- const TOKEN_FILE = join ( CONFIG_DIR , 'tokens.json' ) ;
7+ const DEFAULT_TOKEN_FILE = join ( homedir ( ) , '.whoop-cli' , 'tokens.json' ) ;
8+
9+ function getTokenFilePath ( ) : string {
10+ const envPath = process . env . WHOOP_TOKEN_FILE ?. trim ( ) ;
11+ if ( ! envPath ) {
12+ return DEFAULT_TOKEN_FILE ;
13+ }
14+
15+ // Resolve relative paths against current working directory
16+ return resolve ( envPath ) ;
17+ }
18+
19+ function getConfigDir ( ) : string {
20+ return dirname ( getTokenFilePath ( ) ) ;
21+ }
922
1023// Refresh tokens 15 minutes before expiry to avoid race conditions
1124const REFRESH_BUFFER_SECONDS = 900 ;
1225
1326function ensureConfigDir ( ) : void {
14- if ( ! existsSync ( CONFIG_DIR ) ) {
15- mkdirSync ( CONFIG_DIR , { recursive : true , mode : 0o700 } ) ;
27+ const configDir = getConfigDir ( ) ;
28+ if ( ! existsSync ( configDir ) ) {
29+ mkdirSync ( configDir , { recursive : true , mode : 0o700 } ) ;
1630 }
1731}
1832
1933export function saveTokens ( response : OAuthTokenResponse ) : void {
2034 ensureConfigDir ( ) ;
35+ const tokenFile = getTokenFilePath ( ) ;
2136
2237 const data : TokenData = {
2338 access_token : response . access_token ,
@@ -27,26 +42,28 @@ export function saveTokens(response: OAuthTokenResponse): void {
2742 scope : response . scope ,
2843 } ;
2944
30- writeFileSync ( TOKEN_FILE , JSON . stringify ( data , null , 2 ) ) ;
31- chmodSync ( TOKEN_FILE , 0o600 ) ;
45+ writeFileSync ( tokenFile , JSON . stringify ( data , null , 2 ) ) ;
46+ chmodSync ( tokenFile , 0o600 ) ;
3247}
3348
3449export function loadTokens ( ) : TokenData | null {
35- if ( ! existsSync ( TOKEN_FILE ) ) {
50+ const tokenFile = getTokenFilePath ( ) ;
51+ if ( ! existsSync ( tokenFile ) ) {
3652 return null ;
3753 }
3854
3955 try {
40- const content = readFileSync ( TOKEN_FILE , 'utf-8' ) ;
56+ const content = readFileSync ( tokenFile , 'utf-8' ) ;
4157 return JSON . parse ( content ) as TokenData ;
4258 } catch {
4359 return null ;
4460 }
4561}
4662
4763export function clearTokens ( ) : void {
48- if ( existsSync ( TOKEN_FILE ) ) {
49- writeFileSync ( TOKEN_FILE , '' ) ;
64+ const tokenFile = getTokenFilePath ( ) ;
65+ if ( existsSync ( tokenFile ) ) {
66+ writeFileSync ( tokenFile , '' ) ;
5067 }
5168}
5269
0 commit comments