1+ var async = require ( 'async' ) ;
2+ var Q = require ( 'q' ) ;
3+ var request = require ( 'request' ) ;
4+ var semver = require ( 'semver' ) ;
5+ var Constants = require ( '../Constants' ) ;
6+ var _ = require ( 'lodash' ) ;
7+
8+ module . exports = function ( ) {
9+ var deferred = Q . defer ( ) ;
10+
11+ checkLatestAdaptRepoVersion ( function ( error , latestFrameworkTag ) {
12+ if ( error ) {
13+ deferred . reject ( error ) ;
14+ } else {
15+ deferred . resolve ( latestFrameworkTag ) ;
16+ }
17+ } ) ;
18+
19+ return deferred . promise ;
20+ }
21+
22+ function checkLatestAdaptRepoVersion ( versionLimit , callback ) {
23+ if ( typeof versionLimit === 'function' ) {
24+ callback = versionLimit ;
25+ versionLimit = undefined ;
26+ }
27+ // used in pagination
28+ var nextPage = `https://api.github.com/repos/${ Constants . DefaultGitHubOrg } /${ Constants . FrameworkRepositoryName } /releases` ;
29+
30+ var _getReleases = function ( done ) {
31+ request ( {
32+ headers : {
33+ 'User-Agent' : Constants . DefaultUserAgent
34+ } ,
35+ uri : nextPage ,
36+ method : 'GET'
37+ } , done ) ;
38+ } ;
39+ var _requestHandler = function ( error , response , body ) {
40+ if ( response ) {
41+ // we've exceeded the API limit
42+ if ( response . statusCode === 403 && response . headers [ 'x-ratelimit-remaining' ] === '0' ) {
43+ var reqsReset = new Date ( response . headers [ 'x-ratelimit-reset' ] * 1000 ) ;
44+ error = `You have exceeded GitHub's request limit of ${ response . headers [ 'x-ratelimit-limit' ] } requests per hour. Please wait until at least ${ reqsReset . toTimeString ( ) } before trying again.` ;
45+ }
46+ else if ( response . statusCode !== 200 ) {
47+ error = 'GitubAPI did not respond with a 200 status code.' ;
48+ }
49+ }
50+ if ( error ) {
51+ return callback ( new Error ( `Couldn't check latest version of ${ Constants . FrameworkRepositoryName } . ${ error } ` ) ) ;
52+ }
53+ nextPage = parseLinkHeader ( response . headers . link ) . next ;
54+ try {
55+ // parse and sort releases (newest first)
56+ var releases = JSON . parse ( body ) . sort ( ( a , b ) => {
57+ if ( semver . lt ( a . tag_name , b . tag_name ) ) return 1 ;
58+ if ( semver . gt ( a . tag_name , b . tag_name ) ) return - 1 ;
59+ return 0 ;
60+ } ) ;
61+ } catch ( e ) {
62+ return callback ( new Error ( `Failed to parse GitHub release data\n${ e } ` ) ) ;
63+ }
64+ var compatibleRelease ;
65+ async . someSeries ( releases , function ( release , cb ) {
66+ var isFullRelease = ! release . draft && ! release . prerelease ;
67+ var satisfiesVersion = ! versionLimit || semver . satisfies ( release . tag_name , versionLimit ) ;
68+
69+ if ( ! isFullRelease || ! satisfiesVersion ) {
70+ return cb ( null , false ) ;
71+ }
72+
73+ compatibleRelease = release ;
74+ return cb ( null , true ) ;
75+ } , function ( error , satisfied ) {
76+ if ( ! satisfied ) {
77+ if ( nextPage ) {
78+ return _getReleases ( _requestHandler ) ;
79+ }
80+ error = new Error ( `Couldn't find any releases compatible with specified framework version (${ versionLimit } ), please check that it is a valid version.` ) ;
81+ }
82+ if ( error ) {
83+ return callback ( error ) ;
84+ }
85+ callback ( error , compatibleRelease . tag_name ) ;
86+ } ) ;
87+ } ;
88+ // start recursion
89+ _getReleases ( _requestHandler ) ;
90+ }
91+
92+ // taken from https://gist.github.com/niallo/3109252
93+ function parseLinkHeader ( header ) {
94+ if ( ! header || header . length === 0 ) {
95+ return [ ] ;
96+ }
97+ var links = { } ;
98+ // Parse each part into a named link
99+ _ . each ( header . split ( ',' ) , function ( p ) {
100+ var section = p . split ( ';' ) ;
101+ if ( section . length !== 2 ) {
102+ throw new Error ( "section could not be split on ';'" ) ;
103+ }
104+ var url = section [ 0 ] . replace ( / < ( .* ) > / , '$1' ) . trim ( ) ;
105+ var name = section [ 1 ] . replace ( / r e l = " ( .* ) " / , '$1' ) . trim ( ) ;
106+ links [ name ] = url ;
107+ } ) ;
108+ return links ;
109+ }
0 commit comments