/ services / api / firstTokenDate.ts
firstTokenDate.ts
 1  import axios from 'axios'
 2  import { getOauthConfig } from '../../constants/oauth.js'
 3  import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js'
 4  import { getAuthHeaders } from '../../utils/http.js'
 5  import { logError } from '../../utils/log.js'
 6  import { getClaudeCodeUserAgent } from '../../utils/userAgent.js'
 7  
 8  /**
 9   * Fetch the user's first Claude Code token date and store in config.
10   * This is called after successful login to cache when they started using Claude Code.
11   */
12  export async function fetchAndStoreClaudeCodeFirstTokenDate(): Promise<void> {
13    try {
14      const config = getGlobalConfig()
15  
16      if (config.claudeCodeFirstTokenDate !== undefined) {
17        return
18      }
19  
20      const authHeaders = getAuthHeaders()
21      if (authHeaders.error) {
22        logError(new Error(`Failed to get auth headers: ${authHeaders.error}`))
23        return
24      }
25  
26      const oauthConfig = getOauthConfig()
27      const url = `${oauthConfig.BASE_API_URL}/api/organization/claude_code_first_token_date`
28  
29      const response = await axios.get(url, {
30        headers: {
31          ...authHeaders.headers,
32          'User-Agent': getClaudeCodeUserAgent(),
33        },
34        timeout: 10000,
35      })
36  
37      const firstTokenDate = response.data?.first_token_date ?? null
38  
39      // Validate the date if it's not null
40      if (firstTokenDate !== null) {
41        const dateTime = new Date(firstTokenDate).getTime()
42        if (isNaN(dateTime)) {
43          logError(
44            new Error(
45              `Received invalid first_token_date from API: ${firstTokenDate}`,
46            ),
47          )
48          // Don't save invalid dates
49          return
50        }
51      }
52  
53      saveGlobalConfig(current => ({
54        ...current,
55        claudeCodeFirstTokenDate: firstTokenDate,
56      }))
57    } catch (error) {
58      logError(error)
59    }
60  }