@@ -4,11 +4,38 @@ import {fetch} from '../fetch';
44import logger from '../logger' ;
55
66export type Release = {
7- version : string ;
7+ // The current stable release
8+ stable : string ;
9+ // The current candidate release. These are only populated if the latest release is a candidate release.
10+ candidate ?: string ;
811 changelogUrl : string ;
912 diffUrl : string ;
1013} ;
1114
15+ interface DiffPurge {
16+ name : string ;
17+ zipball_url : string ;
18+ tarball_url : string ;
19+ commit : {
20+ sha : string ;
21+ url : string ;
22+ } ;
23+ node_id : string ;
24+ }
25+
26+ function isDiffPurgeEntry ( data : any ) : data is DiffPurge {
27+ return (
28+ [
29+ data . name ,
30+ data . zipball_url ,
31+ data . tarball_url ,
32+ data . commit ?. sha ,
33+ data . commit ?. url ,
34+ data . node_id ,
35+ ] . indexOf ( false ) === - 1
36+ ) ;
37+ }
38+
1239/**
1340 * Checks via GitHub API if there is a newer stable React Native release and,
1441 * if it exists, returns the release data.
@@ -49,17 +76,15 @@ export default async function getLatestRelease(
4976
5077 logger . debug ( 'Checking for newer releases on GitHub' ) ;
5178 const eTag = cacheManager . get ( name , 'eTag' ) ;
52- const latestVersion = await getLatestRnDiffPurgeVersion ( name , eTag ) ;
53- logger . debug ( `Latest release: ${ latestVersion } ` ) ;
79+ const { stable , candidate } = await getLatestRnDiffPurgeVersion ( name , eTag ) ;
80+ logger . debug ( `Latest release: ${ stable } ( ${ candidate } ) ` ) ;
5481
55- if (
56- semver . compare ( latestVersion , currentVersion ) === 1 &&
57- ! semver . prerelease ( latestVersion )
58- ) {
82+ if ( semver . compare ( stable , currentVersion ) >= 0 ) {
5983 return {
60- version : latestVersion ,
61- changelogUrl : buildChangelogUrl ( latestVersion ) ,
62- diffUrl : buildDiffUrl ( currentVersion ) ,
84+ stable,
85+ candidate,
86+ changelogUrl : buildChangelogUrl ( stable ) ,
87+ diffUrl : buildDiffUrl ( stable ) ,
6388 } ;
6489 }
6590 } catch ( e ) {
@@ -79,13 +104,18 @@ function buildDiffUrl(version: string) {
79104 return `https://react-native-community.github.io/upgrade-helper/?from=${ version } ` ;
80105}
81106
107+ type LatestVersions = {
108+ candidate ?: string ;
109+ stable : string ;
110+ } ;
111+
82112/**
83113 * Returns the most recent React Native version available to upgrade to.
84114 */
85115async function getLatestRnDiffPurgeVersion (
86116 name : string ,
87117 eTag ?: string ,
88- ) : Promise < string > {
118+ ) : Promise < LatestVersions > {
89119 const options = {
90120 // https://developer.github.com/v3/#user-agent-required
91121 headers : { 'User-Agent' : 'React-Native-CLI' } as Headers ,
@@ -100,32 +130,38 @@ async function getLatestRnDiffPurgeVersion(
100130 options ,
101131 ) ;
102132
133+ const result : LatestVersions = { stable : '0.0.0' } ;
134+
103135 // Remote is newer.
104136 if ( status === 200 ) {
105- const body : Array < any > = data ;
106- const latestVersion = body [ 0 ] . name . substring ( 8 ) ;
137+ const body : DiffPurge [ ] = data . filter ( isDiffPurgeEntry ) ;
107138 const eTagHeader = headers . get ( 'eTag' ) ;
108139
109- // Update cache only if newer release is stable.
110- if ( ! semver . prerelease ( latestVersion ) && eTagHeader ) {
111- logger . debug ( `Saving ${ eTagHeader } to cache` ) ;
112- cacheManager . set ( name , 'eTag' , eTagHeader ) ;
113- cacheManager . set ( name , 'latestVersion' , latestVersion ) ;
140+ for ( let { name : version } of body ) {
141+ if ( ! result . candidate && version . includes ( '-rc' ) ) {
142+ result . candidate = version . substring ( 8 ) ;
143+ continue ;
144+ }
145+ if ( ! version . includes ( '-rc' ) ) {
146+ result . stable = version . substring ( 8 ) ;
147+ if ( eTagHeader ) {
148+ logger . debug ( `Saving ${ eTagHeader } to cache` ) ;
149+ cacheManager . set ( name , 'eTag' , eTagHeader ) ;
150+ cacheManager . set ( name , 'latestVersion' , result . stable ) ;
151+ }
152+ return result ;
153+ }
114154 }
115-
116- return latestVersion ;
155+ return result ;
117156 }
118157
119158 // Cache is still valid.
120159 if ( status === 304 ) {
121- const latestVersion = cacheManager . get ( name , 'latestVersion' ) ;
122- if ( latestVersion ) {
123- return latestVersion ;
124- }
160+ result . stable = cacheManager . get ( name , 'latestVersion' ) ?? result . stable ;
125161 }
126162
127163 // Should be returned only if something went wrong.
128- return '0.0.0' ;
164+ return result ;
129165}
130166
131167type Headers = {
0 commit comments