@@ -74,38 +74,36 @@ export class PackageJSONContribution implements IJSONContribution {
7474 let queryUrl : string ;
7575 if ( currentWord . length > 0 ) {
7676 if ( currentWord [ 0 ] === '@' ) {
77- return this . collectScopedPackages ( currentWord , addValue , isLast , collector ) ;
77+ if ( currentWord . indexOf ( '/' ) !== - 1 ) {
78+ return this . collectScopedPackages ( currentWord , addValue , isLast , collector ) ;
79+ }
80+ for ( let scope of this . knownScopes ) {
81+ const proposal = new CompletionItem ( scope ) ;
82+ proposal . kind = CompletionItemKind . Property ;
83+ proposal . insertText = new SnippetString ( ) . appendText ( `"${ scope } /` ) . appendTabstop ( ) . appendText ( '"' ) ;
84+ proposal . filterText = JSON . stringify ( scope ) ;
85+ proposal . documentation = '' ;
86+ proposal . command = {
87+ title : '' ,
88+ command : 'editor.action.triggerSuggest'
89+ } ;
90+ collector . add ( proposal ) ;
91+ }
92+ collector . setAsIncomplete ( ) ;
7893 }
7994
80- queryUrl = 'https://skimdb.npmjs.com/registry/_design/app/_view/browseAll?group_level=2&limit=' + LIMIT + '&start_key=%5B%22' + encodeURIComponent ( currentWord ) + '%22%5D&end_key=%5B%22' + encodeURIComponent ( currentWord + 'z' ) + '%22,%7B%7D%5D' ;
81-
95+ queryUrl = `https://api.npms.io/v2/search/suggestions?size=${ LIMIT } &q=${ encodeURIComponent ( currentWord ) } ` ;
8296 return this . xhr ( {
8397 url : queryUrl ,
8498 agent : USER_AGENT
8599 } ) . then ( ( success ) => {
86100 if ( success . status === 200 ) {
87101 try {
88102 const obj = JSON . parse ( success . responseText ) ;
89- if ( obj && Array . isArray ( obj . rows ) ) {
90- const results = < { key : string [ ] ; } [ ] > obj . rows ;
103+ if ( obj && Array . isArray ( obj ) ) {
104+ const results = < { package : SearchPackageInfo ; } [ ] > obj ;
91105 for ( const result of results ) {
92- const keys = result . key ;
93- if ( Array . isArray ( keys ) && keys . length > 0 ) {
94- const name = keys [ 0 ] ;
95- const insertText = new SnippetString ( ) . appendText ( JSON . stringify ( name ) ) ;
96- if ( addValue ) {
97- insertText . appendText ( ': "' ) . appendTabstop ( ) . appendText ( '"' ) ;
98- if ( ! isLast ) {
99- insertText . appendText ( ',' ) ;
100- }
101- }
102- const proposal = new CompletionItem ( name ) ;
103- proposal . kind = CompletionItemKind . Property ;
104- proposal . insertText = insertText ;
105- proposal . filterText = JSON . stringify ( name ) ;
106- proposal . documentation = keys [ 1 ] ;
107- collector . add ( proposal ) ;
108- }
106+ this . processPackage ( result . package , addValue , isLast , collector ) ;
109107 }
110108 if ( results . length === LIMIT ) {
111109 collector . setAsIncomplete ( ) ;
@@ -149,20 +147,7 @@ export class PackageJSONContribution implements IJSONContribution {
149147
150148 private collectScopedPackages ( currentWord : string , addValue : boolean , isLast : boolean , collector : ISuggestionsCollector ) : Thenable < any > {
151149 let segments = currentWord . split ( '/' ) ;
152- if ( segments . length === 1 ) {
153- for ( let scope of this . knownScopes ) {
154- const proposal = new CompletionItem ( scope ) ;
155- proposal . kind = CompletionItemKind . Property ;
156- proposal . insertText = new SnippetString ( ) . appendText ( `"${ scope } /` ) . appendTabstop ( ) . appendText ( '"' ) ;
157- proposal . filterText = JSON . stringify ( scope ) ;
158- proposal . documentation = '' ;
159- proposal . command = {
160- title : '' ,
161- command : 'editor.action.triggerSuggest'
162- } ;
163- collector . add ( proposal ) ;
164- }
165- } else if ( segments . length === 2 && segments [ 0 ] . length > 1 ) {
150+ if ( segments . length === 2 && segments [ 0 ] . length > 1 ) {
166151 let scope = segments [ 0 ] . substr ( 1 ) ;
167152 let name = segments [ 1 ] ;
168153 if ( name . length < 4 ) {
@@ -177,30 +162,9 @@ export class PackageJSONContribution implements IJSONContribution {
177162 try {
178163 const obj = JSON . parse ( success . responseText ) ;
179164 if ( obj && Array . isArray ( obj . results ) ) {
180- const objects = < { package : { name : string ; version : string , description : string ; } } [ ] > obj . results ;
165+ const objects = < { package : SearchPackageInfo } [ ] > obj . results ;
181166 for ( let object of objects ) {
182- if ( object . package && object . package . name ) {
183- const name = object . package . name ;
184- const insertText = new SnippetString ( ) . appendText ( JSON . stringify ( name ) ) ;
185- if ( addValue ) {
186- insertText . appendText ( ': "' ) ;
187- if ( object . package . version ) {
188- insertText . appendVariable ( 'version' , object . package . version ) ;
189- } else {
190- insertText . appendTabstop ( ) ;
191- }
192- insertText . appendText ( '"' ) ;
193- if ( ! isLast ) {
194- insertText . appendText ( ',' ) ;
195- }
196- }
197- const proposal = new CompletionItem ( name ) ;
198- proposal . kind = CompletionItemKind . Property ;
199- proposal . insertText = insertText ;
200- proposal . filterText = JSON . stringify ( name ) ;
201- proposal . documentation = object . package . description || '' ;
202- collector . add ( proposal ) ;
203- }
167+ this . processPackage ( object . package , addValue , isLast , collector ) ;
204168 }
205169 if ( objects . length === SCOPED_LIMIT ) {
206170 collector . setAsIncomplete ( ) ;
@@ -291,19 +255,23 @@ export class PackageJSONContribution implements IJSONContribution {
291255 } ) ;
292256 }
293257
294- private npmView ( pack : string ) : Promise < PackageInfo > {
258+ private npmView ( pack : string ) : Promise < ViewPackageInfo > {
295259 return new Promise ( ( resolve , reject ) => {
296260 const command = 'npm view --json ' + pack + ' description dist-tags.latest homepage' ;
297261 cp . exec ( command , ( error , stdout ) => {
298262 if ( error ) {
299263 return reject ( ) ;
300264 }
301- const content = JSON . parse ( stdout ) ;
302- resolve ( {
303- description : content [ 'description' ] ,
304- distTagsLatest : content [ 'dist-tags.latest' ] ,
305- homepage : content [ 'homepage' ]
306- } ) ;
265+ try {
266+ const content = JSON . parse ( stdout ) ;
267+ resolve ( {
268+ description : content [ 'description' ] ,
269+ distTagsLatest : content [ 'dist-tags.latest' ] ,
270+ homepage : content [ 'homepage' ]
271+ } ) ;
272+ } catch ( e ) {
273+ reject ( ) ;
274+ }
307275 } ) ;
308276 } ) ;
309277 }
@@ -322,9 +290,40 @@ export class PackageJSONContribution implements IJSONContribution {
322290 }
323291 return null ;
324292 }
293+
294+ private processPackage ( pack : SearchPackageInfo , addValue : boolean , isLast : boolean , collector : ISuggestionsCollector ) {
295+ if ( pack && pack . name ) {
296+ const name = pack . name ;
297+ const insertText = new SnippetString ( ) . appendText ( JSON . stringify ( name ) ) ;
298+ if ( addValue ) {
299+ insertText . appendText ( ': "' ) ;
300+ if ( pack . version ) {
301+ insertText . appendVariable ( 'version' , pack . version ) ;
302+ } else {
303+ insertText . appendTabstop ( ) ;
304+ }
305+ insertText . appendText ( '"' ) ;
306+ if ( ! isLast ) {
307+ insertText . appendText ( ',' ) ;
308+ }
309+ }
310+ const proposal = new CompletionItem ( name ) ;
311+ proposal . kind = CompletionItemKind . Property ;
312+ proposal . insertText = insertText ;
313+ proposal . filterText = JSON . stringify ( name ) ;
314+ proposal . documentation = pack . description || '' ;
315+ collector . add ( proposal ) ;
316+ }
317+ }
318+ }
319+
320+ interface SearchPackageInfo {
321+ name : string ;
322+ description ?: string ;
323+ version ?: string ;
325324}
326325
327- interface PackageInfo {
326+ interface ViewPackageInfo {
328327 description : string ;
329328 distTagsLatest ?: string ;
330329 homepage ?: string ;
0 commit comments