11'use strict'
22
3- var npm = require ( './npm.js' )
4- var output = require ( './utils/output.js' )
5- var readPackageTree = require ( 'read-package-tree' )
6- var runParallelLimit = require ( 'run-parallel-limit' )
7- var simpleGet = require ( 'simple-get' )
8- var semver = require ( 'semver' )
9- var hasANSI = require ( 'has-ansi' )
3+ const npm = require ( './npm.js' )
4+ const output = require ( './utils/output.js' )
5+ const path = require ( 'path' )
6+ const readPackageTree = require ( 'read-package-tree' )
7+ const semver = require ( 'semver' )
8+ const validSupportURL = require ( './utils/valid-support-url' )
109
1110module . exports = support
1211
@@ -18,7 +17,6 @@ support.usage = usage(
1817
1918support . completion = function ( opts , cb ) {
2019 const argv = opts . conf . argv . remain
21-
2220 switch ( argv [ 2 ] ) {
2321 case 'support' :
2422 return cb ( null , [ ] )
@@ -27,206 +25,64 @@ support.completion = function (opts, cb) {
2725 }
2826}
2927
28+ // Compare lib/ls.js.
3029function support ( args , silent , cb ) {
31- readPackageTree ( npm . dir , function ( error , tree ) {
32- if ( error ) return cb ( error )
33- var supportablePackages = Array . from ( findSupportablePackages ( tree ) )
34- downloadSupportData ( supportablePackages , function ( error , data ) {
35- if ( error ) return cb ( error )
36-
37- if ( typeof cb !== 'function' ) {
38- cb = silent
39- silent = false
40- }
41- if ( silent ) return cb ( null , data )
42-
43- var out
44- var json = npm . config . get ( 'json' )
45- if ( json ) {
46- out = JSON . stringify ( data , null , 2 )
47- } else {
48- out = data
49- . sort ( function ( a , b ) {
50- var comparison = a . name . localeCompare ( b . name )
51- return comparison === 0
52- ? semver . compare ( a . version , b . version )
53- : comparison
54- } )
55- . map ( displaySupportData )
56- . join ( '\n\n' )
57- }
58- output ( out )
59- if ( error ) process . exitCode = 1
60- cb ( error , data )
61- } )
30+ if ( typeof cb !== 'function' ) {
31+ cb = silent
32+ silent = false
33+ }
34+ const dir = path . resolve ( npm . dir , '..' )
35+ readPackageTree ( dir , function ( err , tree ) {
36+ if ( err ) {
37+ process . exitCode = 1
38+ return cb ( err )
39+ }
40+ const data = findPackages ( tree )
41+ if ( silent ) return cb ( null , data )
42+ var out
43+ if ( npm . config . get ( 'json' ) ) {
44+ out = JSON . stringify ( data , null , 2 )
45+ } else {
46+ out = data . map ( displayPackage ) . join ( '\n\n' )
47+ }
48+ output ( out )
49+ cb ( err , data )
6250 } )
6351}
6452
65- function findSupportablePackages ( root ) {
66- var set = new Set ( )
53+ function findPackages ( root ) {
54+ const set = new Set ( )
6755 iterate ( root )
68- return set
56+ return Array . from ( set ) . sort ( function ( a , b ) {
57+ const comparison = a . name
58+ . toLowerCase ( )
59+ . localeCompare ( b . name . toLowerCase ( ) )
60+ return comparison === 0
61+ ? semver . compare ( a . version , b . version )
62+ : comparison
63+ } )
6964
7065 function iterate ( node ) {
7166 node . children . forEach ( recurse )
7267 }
7368
7469 function recurse ( node ) {
75- var metadata = node . package
76- if ( metadata . support ) {
70+ const metadata = node . package
71+ const support = metadata . support
72+ if ( support && validSupportURL ( support ) ) {
7773 set . add ( {
7874 name : metadata . name ,
7975 version : metadata . version ,
76+ path : node . path ,
8077 homepage : metadata . homepage ,
8178 repository : metadata . repository ,
82- support : metadata . support ,
83- parent : node . parent ,
84- path : node . path
79+ support : metadata . support
8580 } )
8681 }
8782 if ( node . children ) iterate ( node )
8883 }
8984}
9085
91- function downloadSupportData ( supportablePackages , cb ) {
92- var cache = new Map ( )
93- var headers = { 'user-agent' : npm . config . get ( 'user-agent' ) }
94- runParallelLimit ( supportablePackages . map ( function ( entry ) {
95- return function task ( done ) {
96- var url = entry . support
97- get ( url , function ( error , response , projectData ) {
98- if ( error ) {
99- return done ( null , {
100- url : url ,
101- error : 'could not download data'
102- } )
103- }
104- if ( typeof projectData !== 'object' || Array . isArray ( projectData ) ) {
105- return done ( null , {
106- url : url ,
107- error : 'not an object'
108- } )
109- }
110- var contributors = projectData . contributors
111- if ( ! Array . isArray ( contributors ) ) {
112- return done ( null , projectData )
113- }
114- runParallelLimit ( contributors . map ( function ( contributor ) {
115- return function ( done ) {
116- if (
117- typeof contributor !== 'object' ||
118- typeof contributor . url !== 'string'
119- ) {
120- return setImmediate ( function ( ) {
121- done ( null , contributor )
122- } )
123- }
124- get ( contributor . url , function ( error , response , contributorData ) {
125- if ( error ) {
126- return done ( null , {
127- url : contributor . url ,
128- error : error
129- } )
130- }
131- contributorData . url = contributor . url
132- var result = {
133- name : contributorData . name ,
134- type : contributorData . type ,
135- url : contributor . url
136- }
137- if ( looksLikeURL ( contributorData . homepage ) ) {
138- result . homepage = contributorData . homepage
139- }
140- if (
141- Array . isArray ( contributorData . links ) &&
142- contributorData . links . every ( function ( element ) {
143- return looksLikeURL ( element )
144- } )
145- ) {
146- result . links = contributorData . links
147- }
148- done ( null , result )
149- } )
150- }
151- } ) , 5 , function ( error , resolvedContributors ) {
152- if ( error ) return done ( error )
153- done ( null , {
154- name : entry . name ,
155- version : entry . version ,
156- url : entry . support ,
157- homepage : entry . homepage ,
158- contributors : resolvedContributors
159- } )
160- } )
161- } )
162- }
163- } ) , 5 , cb )
164-
165- function get ( url , cb ) {
166- var cached = cache . get ( url )
167- if ( cached ) {
168- return setImmediate ( function ( ) {
169- cb ( null , { cached : true } , cached )
170- } )
171- }
172- simpleGet . concat ( {
173- url : url ,
174- json : true ,
175- headers : headers
176- } , function ( err , response , data ) {
177- if ( err ) return cb ( err )
178- cache . set ( url , data )
179- cb ( null , response , data )
180- } )
181- }
182- }
183-
184- function displaySupportData ( entry ) {
185- var returned = [ entry . name + '@' + entry . version ]
186- if ( looksLikeURL ( entry . homepage ) ) {
187- returned [ 0 ] += ' (' + entry . homepage + ')'
188- }
189- if ( Array . isArray ( entry . contributors ) ) {
190- entry . contributors . forEach ( function ( contributor ) {
191- var name = contributor . name
192- if ( looksLikeSafeString ( name ) ) {
193- var item = [ '- ' + name ]
194- var email = contributor . email
195- if ( looksLikeSafeString ( email ) ) {
196- item [ 0 ] += ' <' + email + '>'
197- }
198- var homepage = contributor . homepage
199- if ( looksLikeURL ( homepage ) ) {
200- item [ 0 ] += ' (' + homepage + ')'
201- }
202- var links = contributor . links
203- if ( Array . isArray ( links ) ) {
204- links . forEach ( function ( link ) {
205- if ( looksLikeURL ( link ) ) item . push ( ' ' + link )
206- } )
207- }
208- returned . push ( item . join ( '\n' ) )
209- }
210- } )
211- }
212- return returned . join ( '\n' )
213- }
214-
215- function looksLikeSafeString ( argument ) {
216- return (
217- typeof argument === 'string' &&
218- argument . length > 0 &&
219- argument . length < 80 &&
220- ! hasANSI ( argument )
221- )
222- }
223-
224- function looksLikeURL ( argument ) {
225- return (
226- looksLikeSafeString ( argument ) &&
227- (
228- argument . indexOf ( 'https://' ) === 0 ||
229- argument . indexOf ( 'http://' ) === 0
230- )
231- )
86+ function displayPackage ( entry ) {
87+ return entry . name + '@' + entry . version + ': ' + entry . support
23288}
0 commit comments