Skip to content

Refactoring #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 17 additions & 48 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,81 +111,58 @@
{
"name": "Sync on iOS",
"type": "nativescript",
"platform": "ios",
"request": "launch",
"platform": "ios",
"appRoot": "${workspaceRoot}",
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false,
"rebuild": false,
"syncAllFiles": false
"sourceMaps": true
},
{
"name": "Launch on iOS",
"type": "nativescript",
"platform": "ios",
"request": "launch",
"platform": "ios",
"appRoot": "${workspaceRoot}",
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false,
"rebuild": true
},
{
"name": "Attach on iOS",
"type": "nativescript",
"platform": "ios",
"request": "attach",
"platform": "ios",
"appRoot": "${workspaceRoot}",
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false
"sourceMaps": true
},
{
"name": "Sync on Android",
"type": "nativescript",
"platform": "android",
"request": "launch",
"platform": "android",
"appRoot": "${workspaceRoot}",
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false,
"rebuild": false
"sourceMaps": true
},
{
"name": "Launch on Android",
"type": "nativescript",
"platform": "android",
"request": "launch",
"platform": "android",
"appRoot": "${workspaceRoot}",
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false,
"rebuild": true
},
{
"name": "Attach on Android",
"type": "nativescript",
"platform": "android",
"request": "attach",
"platform": "android",
"appRoot": "${workspaceRoot}",
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false
"sourceMaps": true
}
],
"configurationAttributes": {
"launch": {
"required": [],
"properties": {
"runtimeArgs": {
"type": "array",
"description": "Optional arguments passed to the runtime executable.",
"items": {
"type": "string"
},
"default": []
},
"tnsArgs": {
"type": "array",
"description": "Optional arguments passed to the NativeScript CLI executable.",
Expand Down Expand Up @@ -219,9 +196,14 @@
"description": "NativeScript platform",
"default": null
},
"emulator": {
"stopOnEntry": {
"type": "boolean",
"description": "Whether the app to run in emulator or on a physical device.",
"description": "Automatically stop on the first line after lauch",
"default": false
},
"noDebug": {
"type": "boolean",
"description": "If true the launch request will launch the program without enabling debugging",
"default": false
},
"rebuild": {
Expand All @@ -244,14 +226,6 @@
"attach": {
"required": [],
"properties": {
"runtimeArgs": {
"type": "array",
"description": "Optional arguments passed to the runtime executable.",
"items": {
"type": "string"
},
"default": []
},
"tnsArgs": {
"type": "array",
"description": "Optional arguments passed to the NativeScript CLI executable.",
Expand Down Expand Up @@ -285,11 +259,6 @@
"description": "NativeScript platform",
"default": null
},
"emulator": {
"type": "boolean",
"description": "Whether the app to run in emulator or on a physical device.",
"default": false
},
"nativescriptCliPath": {
"type": "string",
"description": "Path to the nativescript CLI to be used by the NativeScript extension.",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
import * as os from 'os';
import * as vscode from 'vscode';
import { Version } from '../../common/Version';
import { Version } from '../common/version';
import { GUAService } from './GUAService';
import { TelerikAnalyticsService } from './TelerikAnalyticsService';
import { AnalyticsBaseInfo, OperatingSystem } from './AnalyticsBaseInfo';
import { ExtensionVersionInfo } from '../ExtensionVersionInfo';
import * as ns from '../NsCliService';
import { ExtensionHostServices as Services } from '../services/extensionHostServices';
import * as utils from '../common/utilities';

export class AnalyticsService {
private static _instance: AnalyticsService;

private _baseInfo: AnalyticsBaseInfo;
private _gua: GUAService;
private _ta: TelerikAnalyticsService;
private _analyticsEnabled: boolean;

public static getInstance(): AnalyticsService {
if (!this._instance) {
this._instance = new AnalyticsService();
}
return this._instance;
}

public static generateMachineId(): string {
let machineId = '';
try {
Expand All @@ -48,8 +39,8 @@ export class AnalyticsService {
};

this._baseInfo = {
cliVersion: Version.stringify(ns.CliVersionInfo.getInstalledCliVersion()),
extensionVersion: Version.stringify(ExtensionVersionInfo.getExtensionVersion()),
cliVersion: Services.cli.version.toString(),
extensionVersion: utils.getInstalledExtensionVersion().toString(),
operatingSystem: operatingSystem,
userId: AnalyticsService.generateMachineId()
};
Expand Down Expand Up @@ -79,7 +70,7 @@ export class AnalyticsService {
this._gua.runRunCommand(platform),
this._ta.runRunCommand(platform)
]);
} catch(e) {}
} catch(e) { }
}
return Promise.resolve();
}
Expand Down
File renamed without changes.
101 changes: 101 additions & 0 deletions src/common/Logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as fs from 'fs';

export enum LoggerMessageType {
Log,
Info,
Warning,
Error
}

export interface LoggerMessageEventArgs {
message: string,
type: LoggerMessageType
}

export type LoggerHandler = ((args: LoggerMessageEventArgs) => void);
type TaggedLoggerHandler = { handler: LoggerHandler, tags: string[] };

/**
* The logger is a singleton.
*/
export class Logger {
private _handlers: TaggedLoggerHandler[];

constructor() {
this._handlers = [];
}

private handleMessage(message: string, type: LoggerMessageType = LoggerMessageType.Log, tag: string = null) {
for (let handler of this._handlers) {
if (!handler.tags || handler.tags.length == 0 || handler.tags.indexOf(tag) > -1) {
handler.handler({ message: message, type: type });
}
}
}

public log(message: string, tag: string = null): void {
this.handleMessage(message, LoggerMessageType.Log, tag);
}

public info(message: string, tag: string = null): void {
this.handleMessage(message, LoggerMessageType.Info, tag);
}

public warn(message: string, tag: string = null): void {
this.handleMessage(message, LoggerMessageType.Warning, tag);
}

public error(message: string, tag: string = null): void {
this.handleMessage(message, LoggerMessageType.Error, tag);
}

public addHandler(handler: LoggerHandler, tags: string[] = null) {
tags = tags || [];
this._handlers.push({ handler: handler, tags: tags });
}

/**
* Removes all occurrence of this handler, ignoring the associated tags
*/
public removeHandler(handlerToRemove: LoggerHandler) {
let i = this._handlers.length;
while (i--) {
if (this._handlers[i].handler == handlerToRemove) {
this._handlers.splice(i, 1);
}
}
}
}

export namespace Tags {
export const FrontendMessage: string = "LoggerTag.FrontendMessage";
}

export namespace Handlers {
export function stdStreamsHandler(args: LoggerMessageEventArgs) {
switch(args.type) {
case LoggerMessageType.Log:
console.log(args.message);
break;
case LoggerMessageType.Info:
console.info(args.message);
break;
case LoggerMessageType.Warning:
console.warn(args.message);
break;
case LoggerMessageType.Error:
console.error(args.message);
break;
}
};

export function createStreamHandler(stream: fs.WriteStream, encoding: string = 'utf8'): LoggerHandler {
let isStreamClosed = false;
stream.on('close', () => { isStreamClosed = true; });
return (args: LoggerMessageEventArgs) => {
if (stream && !isStreamClosed) {
stream.write(args.message, encoding);
}
}
}
}
20 changes: 0 additions & 20 deletions src/common/Version.ts

This file was deleted.

84 changes: 84 additions & 0 deletions src/common/extensionVersionService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import * as https from 'https';
import * as vscode from 'vscode';
import {Version} from './version';
import * as utils from './utilities';

export type LatestPublishedVersionCheckResult = {latestPublishedVersion: string, timestamp: number};

export class ExtensionVersionService {
private static _extensionId: string = '8d837914-d8fa-45b5-965d-f76ebd6dbf5c';
private static _getLatestPublishedVersionPromise: Promise<LatestPublishedVersionCheckResult> = null;
private _memento: vscode.Memento;

private static getExtensionMetadataFromVSCodeMarketplace(): Promise<LatestPublishedVersionCheckResult> {
return new Promise<LatestPublishedVersionCheckResult>((resolve, reject) =>{
let postData: string = `{ filters: [{ criteria: [{ filterType: 4, value: "${ExtensionVersionService._extensionId}" }] }], flags: 262 }`;

let request = https.request({
hostname: 'marketplace.visualstudio.com',
path: '/_apis/public/gallery/extensionquery',
method: 'POST',
headers: {
'Accept': 'application/json;api-version=2.2-preview.1',
'Content-Type': 'application/json',
'Transfer-Encoding': 'chunked',
'Content-Length': Buffer.byteLength(postData)
}
}, response => {
if (response.statusCode != 200) {
reject(`Unable to download data from Visual Studio Marketplace. Status code: ${response.statusCode}`);
return;
}
let body = '';
response.on('data', chunk => {
body += chunk;
});
response.on('end', () => {
let bodyObj = JSON.parse(body);
if (bodyObj.results[0].extensions[0].extensionId == ExtensionVersionService._extensionId) {
let latestPublishedVersion = bodyObj.results[0].extensions[0].versions[0].version;
resolve({ latestPublishedVersion: latestPublishedVersion, timestamp: Date.now() });
}
});
});

request.on('error', (e) => {
reject(e);
});

request.end(postData);
});
}

constructor(context: vscode.Memento) {
this._memento = context;
}

public get latestPublishedVersion(): Promise<Version> {
if (ExtensionVersionService._getLatestPublishedVersionPromise) {
return ExtensionVersionService._getLatestPublishedVersionPromise.then(result => Version.parse(result.latestPublishedVersion) );
}

// Check the cache for extension version information
let cachedResult: LatestPublishedVersionCheckResult = this._memento.get<LatestPublishedVersionCheckResult>('LatestPublishedExtensionVersion');
if (cachedResult && cachedResult.timestamp > Date.now() - 24 * 60 * 60 * 1000) { // Version is cached for a day
ExtensionVersionService._getLatestPublishedVersionPromise = Promise.resolve(cachedResult);
}
else {
ExtensionVersionService._getLatestPublishedVersionPromise = ExtensionVersionService.getExtensionMetadataFromVSCodeMarketplace().then((result: LatestPublishedVersionCheckResult) => {
this._memento.update('LatestPublishedExtensionVersion', result); // save in cache
return result;
});
}
return ExtensionVersionService._getLatestPublishedVersionPromise.then(result => Version.parse(result.latestPublishedVersion));
}

public get isLatestInstalled(): Promise<{ result: boolean, error: string }> {
return this.latestPublishedVersion.then(latestVersion => {
let extensionVersion = utils.getInstalledExtensionVersion();
let isLatest: boolean = extensionVersion.compareBySubminorTo(latestVersion) >= 0;
let error = isLatest ? null : `A new version of the NativeScript extension is available. Open "Extensions" panel to update to v${latestVersion}.`;
return {result: isLatest, error: error};
});
}
}
Loading