1+ #!/usr/bin/env node
2+
3+ import { existsSync , mkdirSync , readFileSync , writeFileSync } from 'node:fs'
4+ import path from 'node:path'
5+ import { fileURLToPath } from 'node:url'
6+
7+ const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
8+ const outputDir = path . resolve ( __dirname , '../docs/.vitepress/data' )
9+ const outputFile = path . join ( outputDir , 'xmake-release.js' )
10+ const releaseApiUrl = 'https://api.github.com/repos/xmake-io/xmake/releases/latest'
11+ const releasePageUrl = 'https://github.com/xmake-io/xmake/releases/latest'
12+ const outputPrefix = 'export const xmakeRelease = '
13+
14+ const emptyRelease = {
15+ tagName : '' ,
16+ name : '' ,
17+ url : releasePageUrl ,
18+ publishedAt : '' ,
19+ fetchedAt : ''
20+ }
21+
22+ function ensureOutputDir ( ) {
23+ if ( ! existsSync ( outputDir ) ) {
24+ mkdirSync ( outputDir , { recursive : true } )
25+ }
26+ }
27+
28+ function serializeRelease ( release ) {
29+ return `${ outputPrefix } ${ JSON . stringify ( release , null , 2 ) } \n`
30+ }
31+
32+ function readCachedRelease ( ) {
33+ if ( ! existsSync ( outputFile ) ) {
34+ return { ...emptyRelease }
35+ }
36+
37+ try {
38+ const content = readFileSync ( outputFile , 'utf8' ) . trim ( )
39+ if ( ! content . startsWith ( outputPrefix ) ) {
40+ return { ...emptyRelease }
41+ }
42+
43+ const cachedRelease = JSON . parse ( content . slice ( outputPrefix . length ) )
44+ return { ...emptyRelease , ...cachedRelease }
45+ } catch {
46+ return { ...emptyRelease }
47+ }
48+ }
49+
50+ async function fetchLatestRelease ( ) {
51+ const response = await fetch ( releaseApiUrl , {
52+ headers : {
53+ Accept : 'application/vnd.github+json' ,
54+ 'User-Agent' : 'xmake-docs-release-badge'
55+ } ,
56+ signal : AbortSignal . timeout ( 10000 )
57+ } )
58+
59+ if ( ! response . ok ) {
60+ throw new Error ( `GitHub API returned ${ response . status } ` )
61+ }
62+
63+ const payload = await response . json ( )
64+
65+ return {
66+ tagName : typeof payload . tag_name === 'string' ? payload . tag_name . trim ( ) : '' ,
67+ name : typeof payload . name === 'string' ? payload . name . trim ( ) : '' ,
68+ url : typeof payload . html_url === 'string' ? payload . html_url : releasePageUrl ,
69+ publishedAt : typeof payload . published_at === 'string' ? payload . published_at : '' ,
70+ fetchedAt : new Date ( ) . toISOString ( )
71+ }
72+ }
73+
74+ async function main ( ) {
75+ ensureOutputDir ( )
76+
77+ const cachedRelease = readCachedRelease ( )
78+
79+ try {
80+ const latestRelease = await fetchLatestRelease ( )
81+ writeFileSync ( outputFile , serializeRelease ( latestRelease ) )
82+ console . log ( `Generated xmake release data: ${ latestRelease . tagName || 'unknown' } ` )
83+ } catch ( error ) {
84+ const fallbackRelease = {
85+ ...emptyRelease ,
86+ ...cachedRelease ,
87+ fetchedAt : cachedRelease . fetchedAt || new Date ( ) . toISOString ( )
88+ }
89+
90+ writeFileSync ( outputFile , serializeRelease ( fallbackRelease ) )
91+ console . warn ( `Failed to fetch latest xmake release, using cached data instead: ${ error instanceof Error ? error . message : String ( error ) } ` )
92+ }
93+ }
94+
95+ main ( ) . catch ( ( error ) => {
96+ console . error ( 'Unable to generate xmake release data:' , error )
97+ process . exitCode = 1
98+ } )
0 commit comments