/ commands / release-notes / release-notes.ts
release-notes.ts
 1  import type { LocalCommandResult } from '../../types/command.js'
 2  import {
 3    CHANGELOG_URL,
 4    fetchAndStoreChangelog,
 5    getAllReleaseNotes,
 6    getStoredChangelog,
 7  } from '../../utils/releaseNotes.js'
 8  
 9  function formatReleaseNotes(notes: Array<[string, string[]]>): string {
10    return notes
11      .map(([version, notes]) => {
12        const header = `Version ${version}:`
13        const bulletPoints = notes.map(note => `ยท ${note}`).join('\n')
14        return `${header}\n${bulletPoints}`
15      })
16      .join('\n\n')
17  }
18  
19  export async function call(): Promise<LocalCommandResult> {
20    // Try to fetch the latest changelog with a 500ms timeout
21    let freshNotes: Array<[string, string[]]> = []
22  
23    try {
24      const timeoutPromise = new Promise<void>((_, reject) => {
25        setTimeout(rej => rej(new Error('Timeout')), 500, reject)
26      })
27  
28      await Promise.race([fetchAndStoreChangelog(), timeoutPromise])
29      freshNotes = getAllReleaseNotes(await getStoredChangelog())
30    } catch {
31      // Either fetch failed or timed out - just use cached notes
32    }
33  
34    // If we have fresh notes from the quick fetch, use those
35    if (freshNotes.length > 0) {
36      return { type: 'text', value: formatReleaseNotes(freshNotes) }
37    }
38  
39    // Otherwise check cached notes
40    const cachedNotes = getAllReleaseNotes(await getStoredChangelog())
41    if (cachedNotes.length > 0) {
42      return { type: 'text', value: formatReleaseNotes(cachedNotes) }
43    }
44  
45    // Nothing available, show link
46    return {
47      type: 'text',
48      value: `See the full changelog at: ${CHANGELOG_URL}`,
49    }
50  }