1
1
import { exec , execSync , ChildProcess } from 'child_process' ;
2
2
import { EventEmitter } from 'events' ;
3
3
import * as path from 'path' ;
4
+ import * as https from 'https' ;
4
5
import { Logger } from '../webkit/utilities' ;
5
6
import { WebKitConnection } from '../webkit/webKitConnection' ;
6
7
import { AndroidDebugConnection } from './android/androidDebugConnection' ;
@@ -72,9 +73,6 @@ export class IosProject extends NSProject {
72
73
if ( ! this . isOSX ( ) ) {
73
74
return Promise . reject ( 'iOS platform is only supported on OS X.' ) ;
74
75
}
75
- if ( ! CliInfo . isExisting ( ) ) {
76
- return Promise . reject ( CliInfo . getMessage ( ) ) ;
77
- }
78
76
79
77
// build command to execute
80
78
let command : string = new CommandBuilder ( )
@@ -91,9 +89,6 @@ export class IosProject extends NSProject {
91
89
if ( ! this . isOSX ( ) ) {
92
90
return Promise . reject ( 'iOS platform is supported only on OS X.' ) ;
93
91
}
94
- if ( ! CliInfo . isExisting ( ) ) {
95
- return Promise . reject ( CliInfo . getMessage ( ) ) ;
96
- }
97
92
98
93
// build command to execute
99
94
let command : string = new CommandBuilder ( )
@@ -111,10 +106,6 @@ export class IosProject extends NSProject {
111
106
let readyToConnect : boolean = false ;
112
107
113
108
return new Promise < string > ( ( resolve , reject ) => {
114
- if ( ! CliInfo . isCompatible ( ) ) {
115
- this . emit ( 'TNS.outputMessage' , 'WARNING: ' + CliInfo . getMessage ( ) , 'error' ) ;
116
- }
117
-
118
109
// run NativeScript CLI command
119
110
let child : ChildProcess = exec ( command , { cwd : this . projectPath ( ) } ) ;
120
111
@@ -124,9 +115,6 @@ export class IosProject extends NSProject {
124
115
if ( ! readyToConnect ) {
125
116
let matches : RegExpMatchArray = strData . match ( socketPathPattern ) ;
126
117
if ( matches && matches . length > 0 ) {
127
- if ( ! CliInfo . isCompatible ( ) ) {
128
- this . emit ( 'TNS.outputMessage' , 'WARNING: ' + CliInfo . getMessage ( ) , 'error' ) ;
129
- }
130
118
readyToConnect = true ;
131
119
resolve ( matches [ 0 ] . substr ( socketPathPrefix . length ) ) ;
132
120
}
@@ -159,10 +147,6 @@ export class AndroidProject extends NSProject {
159
147
}
160
148
161
149
public run ( emulator : boolean ) : Promise < ChildProcess > {
162
- if ( ! CliInfo . isExisting ( ) ) {
163
- return Promise . reject ( CliInfo . getMessage ( ) ) ;
164
- }
165
-
166
150
// build command to execute
167
151
let command : string = new CommandBuilder ( )
168
152
. appendParam ( "run" )
@@ -302,26 +286,9 @@ class CommandBuilder {
302
286
}
303
287
}
304
288
305
-
306
- export enum CliState {
307
- NotExisting ,
308
- OlderThanSupported ,
309
- NewerThanSupported ,
310
- Compatible
311
- }
312
-
313
- export module CliInfo {
314
- var installedCliVersion : number [ ] ;
315
- var extensionCliVersion : number [ ] ;
316
- let state : CliState ;
317
- let message : string ;
318
-
319
- function compareByMinorVersions ( v1 : number [ ] , v2 : number [ ] ) {
320
- return ( v1 [ 0 ] - v2 [ 0 ] != 0 ) ? ( v1 [ 0 ] - v2 [ 0 ] ) : v1 [ 1 ] - v2 [ 1 ] ;
321
- }
322
-
323
- function parseVersion ( versionStr : string ) : number [ ] {
324
- if ( versionStr == null ) {
289
+ class Version {
290
+ public static parse ( versionStr : string ) : number [ ] {
291
+ if ( versionStr === null ) {
325
292
return null ;
326
293
}
327
294
let version : number [ ] = versionStr . split ( '.' ) . map < number > ( ( str , index , array ) => parseInt ( str ) ) ;
@@ -331,58 +298,170 @@ export module CliInfo {
331
298
return version ;
332
299
}
333
300
334
- function versionToString ( version : number [ ] ) {
301
+ public static stringify ( version : number [ ] ) : string {
335
302
return `${ version [ 0 ] } .${ version [ 1 ] } .${ version [ 2 ] } ` ;
336
303
}
337
304
338
- export function getMessage ( ) {
339
- return message ;
305
+ public static compareBySubminor ( v1 , v2 ) : number {
306
+ return ( v1 [ 0 ] - v2 [ 0 ] != 0 ) ? ( v1 [ 0 ] - v2 [ 0 ] ) : ( v1 [ 1 ] - v2 [ 1 ] != 0 ) ? v1 [ 1 ] - v2 [ 1 ] : v1 [ 2 ] - v2 [ 2 ] ;
340
307
}
308
+ }
341
309
342
- export function getState ( ) {
343
- return state ;
310
+ export class ExtensionVersionInfo {
311
+ private static extensionVersion : number [ ] = null ;
312
+ private static minNativescriptCliVersion : number [ ] = null ;
313
+ private static extensionId : string = '8d837914-d8fa-45b5-965d-f76ebd6dbf5c' ;
314
+ private static marketplaceQueryResult : Promise < any > = null ;
315
+
316
+ private latestVersionMeta : any ;
317
+ private timestamp : number ;
318
+
319
+ private static initVersionsFromPackageJson ( ) {
320
+ let packageJson = require ( '../../package.json' ) ;
321
+ this . extensionVersion = Version . parse ( packageJson . version ) ;
322
+ this . minNativescriptCliVersion = Version . parse ( packageJson . minNativescriptCliVersion ) ;
344
323
}
345
324
346
- export function isExisting ( ) {
347
- return state != CliState . NotExisting ;
325
+ public static getExtensionVersion ( ) : number [ ] {
326
+ if ( this . extensionVersion === null ) {
327
+ this . initVersionsFromPackageJson ( ) ;
328
+ }
329
+ return this . extensionVersion ;
348
330
}
349
331
350
- export function isCompatible ( ) {
351
- return state == CliState . Compatible ;
332
+ public static getMinSupportedNativeScriptVersion ( ) : number [ ] {
333
+ if ( this . minNativescriptCliVersion === null ) {
334
+ this . initVersionsFromPackageJson ( ) ;
335
+ }
336
+ return this . minNativescriptCliVersion ;
352
337
}
353
338
354
- function initialize ( ) {
355
- // get the supported CLI version from package.json
356
- extensionCliVersion = parseVersion ( require ( path . resolve ( __dirname , '../../package.json' ) ) [ 'nativescript-cli-version' ] ) ;
357
- // get the currently installed CLI version
358
- let getVersionCommand : string = new CommandBuilder ( ) . appendParam ( '--version' ) . build ( ) ; // build the command
359
- try {
360
- let versionStr : string = execSync ( getVersionCommand ) . toString ( ) ; // execute it
361
- installedCliVersion = versionStr ? parseVersion ( versionStr ) : null ; // parse the version string
362
- } catch ( e ) {
363
- installedCliVersion = null ;
339
+ public static getMarketplaceExtensionData ( ) : Promise < any > {
340
+ if ( this . marketplaceQueryResult == null ) {
341
+ this . marketplaceQueryResult = new Promise < any > ( ( resolve , reject ) => {
342
+ let postData : string = `{ filters: [{ criteria: [{ filterType: 4, value: "${ ExtensionVersionInfo . extensionId } " }] }], flags: 262 }` ;
343
+
344
+ let request = https . request ( {
345
+ hostname : 'marketplace.visualstudio.com' ,
346
+ path : '/_apis/public/gallery/extensionquery' ,
347
+ method : 'POST' ,
348
+ headers : {
349
+ 'Accept' : 'application/json;api-version=2.2-preview.1' ,
350
+ 'Content-Type' : 'application/json' ,
351
+ 'Transfer-Encoding' : 'chunked' ,
352
+ 'Content-Length' : Buffer . byteLength ( postData )
353
+ }
354
+ } , response => {
355
+ if ( response . statusCode != 200 ) {
356
+ reject ( `Unable to download data from Visual Studio Marketplace. Status code: ${ response . statusCode } ` ) ;
357
+ return ;
358
+ }
359
+ let body = '' ;
360
+ response . on ( 'data' , chunk => {
361
+ body += chunk ;
362
+ } ) ;
363
+ response . on ( 'end' , ( ) => {
364
+ resolve ( JSON . parse ( body ) ) ;
365
+ } ) ;
366
+ } ) ;
367
+
368
+ request . on ( 'error' , ( e ) => {
369
+ reject ( e ) ;
370
+ } ) ;
371
+
372
+ request . end ( postData ) ;
373
+ } ) ;
364
374
}
375
+ return this . marketplaceQueryResult ;
376
+ }
365
377
366
- // initialize the state of the CLI by comparing the installed CLI version and the extension CLI version
367
- if ( installedCliVersion ) {
368
- let compareResult : number = compareByMinorVersions ( installedCliVersion , extensionCliVersion ) ;
369
- if ( compareResult < 0 ) {
370
- state = CliState . OlderThanSupported ;
371
- message = `NativeScript extension is expected to work with NativeScript v${ versionToString ( extensionCliVersion ) } , but currently NativeScript v${ versionToString ( installedCliVersion ) } is installed. This may lead to not working features. Try to update NativeScript by executing 'npm install -g nativescript'.` ;
372
- }
373
- else if ( compareResult > 0 ) {
374
- state = CliState . NewerThanSupported ;
375
- message = `NativeScript extension is expected to work with NativeScript v${ versionToString ( extensionCliVersion ) } , but currently NativeScript v${ versionToString ( installedCliVersion ) } is installed. This may lead to not working features. Try to update the extension by running 'Show Outdated Extensions' command.`
376
- }
377
- else {
378
- state = CliState . Compatible ;
379
- message = null ;
378
+ public static createFromMarketplace ( ) : Promise < ExtensionVersionInfo > {
379
+ return this . getMarketplaceExtensionData ( )
380
+ . then ( marketplaceData => {
381
+ let latestVersion = null ;
382
+ try {
383
+ if ( marketplaceData . results [ 0 ] . extensions [ 0 ] . extensionId == ExtensionVersionInfo . extensionId ) {
384
+ latestVersion = marketplaceData . results [ 0 ] . extensions [ 0 ] . versions [ 0 ] ;
385
+ }
386
+ } catch ( e ) { }
387
+ return new ExtensionVersionInfo ( latestVersion ) ;
388
+ } ) ;
389
+ }
390
+
391
+ constructor ( latestVersionMeta : any , timestamp ?: number ) {
392
+ this . latestVersionMeta = latestVersionMeta ;
393
+ this . timestamp = timestamp || Date . now ( ) ;
394
+ }
395
+
396
+ public getLatestVersionMeta ( ) : any {
397
+ return this . latestVersionMeta ;
398
+ }
399
+
400
+ public isLatest ( ) : boolean {
401
+ if ( ! this . getLatestVersionMeta ( ) ) {
402
+ return true ;
403
+ }
404
+ return Version . compareBySubminor ( ExtensionVersionInfo . getExtensionVersion ( ) , Version . parse ( this . getLatestVersionMeta ( ) . version ) ) >= 0 ;
405
+ }
406
+
407
+ public getTimestamp ( ) : number {
408
+ return this . timestamp ;
409
+ }
410
+ }
411
+
412
+ export enum CliState {
413
+ NotExisting ,
414
+ OlderThanSupported ,
415
+ Compatible
416
+ }
417
+
418
+ export class CliVersionInfo {
419
+ private static installedCliVersion : number [ ] = null ;
420
+
421
+ private _state : CliState ;
422
+
423
+ public static getInstalledCliVersion ( ) : number [ ] {
424
+ if ( this . installedCliVersion === null ) {
425
+ // get the currently installed CLI version
426
+ let getVersionCommand : string = new CommandBuilder ( ) . appendParam ( '--version' ) . build ( ) ; // tns --version
427
+ try {
428
+ let versionStr : string = execSync ( getVersionCommand ) . toString ( ) . trim ( ) ; // execute it
429
+ this . installedCliVersion = versionStr ? Version . parse ( versionStr ) : null ; // parse the version string
430
+ } catch ( e ) {
431
+ this . installedCliVersion = null ;
380
432
}
381
433
}
434
+
435
+ return this . installedCliVersion ;
436
+ }
437
+
438
+ constructor ( ) {
439
+ let installedCliVersion : number [ ] = CliVersionInfo . getInstalledCliVersion ( ) ;
440
+ if ( installedCliVersion === null ) {
441
+ this . _state = CliState . NotExisting ;
442
+ }
382
443
else {
383
- state = CliState . NotExisting ;
384
- message = `NativeScript not found, please run 'npm install –g nativescript@${ versionToString ( extensionCliVersion ) } ' to install it.` ;
444
+ let minSupportedCliVersion = ExtensionVersionInfo . getMinSupportedNativeScriptVersion ( ) ;
445
+ this . _state = Version . compareBySubminor ( installedCliVersion , minSupportedCliVersion ) < 0 ? CliState . OlderThanSupported : CliState . Compatible ;
446
+ }
447
+ }
448
+
449
+ public getState ( ) : CliState {
450
+ return this . _state ;
451
+ }
452
+
453
+ public isCompatible ( ) : boolean {
454
+ return this . _state === CliState . Compatible ;
455
+ }
456
+
457
+ public getErrorMessage ( ) : string {
458
+ switch ( this . _state ) {
459
+ case CliState . NotExisting :
460
+ return `NativeScript CLI not found, please run 'npm install –g nativescript@${ Version . stringify ( ExtensionVersionInfo . getMinSupportedNativeScriptVersion ( ) ) } ' to install it.` ;
461
+ case CliState . OlderThanSupported :
462
+ return `The existing NativeScript extension is compatible with NativeScript CLI v${ Version . stringify ( ExtensionVersionInfo . getMinSupportedNativeScriptVersion ( ) ) } or greater. The currently installed NativeScript CLI is v${ Version . stringify ( CliVersionInfo . getInstalledCliVersion ( ) ) } . You can update the NativeScript CLI by executing 'npm install -g nativescript'.` ;
463
+ default :
464
+ return null ;
385
465
}
386
466
}
387
- initialize ( ) ;
388
467
}
0 commit comments