From 99890c0de80f3c12729b19820f43ebc41f2e6908 Mon Sep 17 00:00:00 2001 From: ivanbuhov Date: Mon, 16 May 2016 17:46:30 +0300 Subject: [PATCH 1/6] Refactoring --- package.json | 2 +- src/common/Version.ts | 20 ++ .../adapter/adapterProxy.ts | 4 +- .../adapter/lineNumberTransformer.ts | 2 +- .../adapter/pathTransformer.ts | 4 +- .../adapter/sourceMaps/pathUtilities.ts | 2 +- .../sourceMaps/sourceMapTransformer.ts | 4 +- .../adapter/sourceMaps/sourceMaps.ts | 4 +- .../connection/INSDebugConnection.ts | 29 ++ .../connection/androidConnection.ts} | 10 +- .../connection/iosConnection.ts} | 9 +- .../consoleHelper.ts | 0 src/{webkit => debug-adapter}/utilities.ts | 4 +- .../webKitAdapterInterfaces.d.ts | 0 src/{webkit => debug-adapter}/webKitDebug.ts | 0 .../webKitDebugAdapter.ts | 21 +- .../webKitDebugSession.ts | 8 +- .../webKitProtocol.d.ts | 0 src/{nativescript/nsMain.ts => main.ts} | 9 +- src/services/ExtensionVersionInfo.ts | 104 +++++++ .../NsCliService.ts} | 271 ++++-------------- src/tsconfig.json | 6 +- 22 files changed, 260 insertions(+), 253 deletions(-) create mode 100644 src/common/Version.ts rename src/{ => debug-adapter}/adapter/adapterProxy.ts (96%) rename src/{ => debug-adapter}/adapter/lineNumberTransformer.ts (96%) rename src/{ => debug-adapter}/adapter/pathTransformer.ts (97%) rename src/{ => debug-adapter}/adapter/sourceMaps/pathUtilities.ts (98%) rename src/{ => debug-adapter}/adapter/sourceMaps/sourceMapTransformer.ts (99%) rename src/{ => debug-adapter}/adapter/sourceMaps/sourceMaps.ts (99%) create mode 100644 src/debug-adapter/connection/INSDebugConnection.ts rename src/{nativescript/android/androidDebugConnection.ts => debug-adapter/connection/androidConnection.ts} (96%) rename src/{webkit/webKitConnection.ts => debug-adapter/connection/iosConnection.ts} (97%) rename src/{webkit => debug-adapter}/consoleHelper.ts (100%) rename src/{webkit => debug-adapter}/utilities.ts (99%) rename src/{webkit => debug-adapter}/webKitAdapterInterfaces.d.ts (100%) rename src/{webkit => debug-adapter}/webKitDebug.ts (100%) rename src/{webkit => debug-adapter}/webKitDebugAdapter.ts (97%) rename src/{webkit => debug-adapter}/webKitDebugSession.ts (94%) rename src/{webkit => debug-adapter}/webKitProtocol.d.ts (100%) rename src/{nativescript/nsMain.ts => main.ts} (91%) create mode 100644 src/services/ExtensionVersionInfo.ts rename src/{nativescript/nativescript.ts => services/NsCliService.ts} (62%) diff --git a/package.json b/package.json index 2da203f..88cc45b 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "test-win": "mocha --opts ./src/tests/config/mocha.opts --config ../../src/tests/config/win.json ./out/tests", "test-custom": "mocha --opts ./src/tests/config/mocha.opts --config ../../src/tests/config/custom.json ./out/tests" }, - "main": "./out/nativescript/nsMain", + "main": "./out/main", "activationEvents": [ "*" ], diff --git a/src/common/Version.ts b/src/common/Version.ts new file mode 100644 index 0000000..424e6d4 --- /dev/null +++ b/src/common/Version.ts @@ -0,0 +1,20 @@ +export class Version { + public static parse(versionStr: string): number[] { + if (versionStr === null) { + return null; + } + let version: number[] = versionStr.split('.').map((str, index, array) => parseInt(str)); + for(let i = version.length; i < 3; i++) { + version.push(0); + } + return version; + } + + public static stringify(version: number[]): string { + return `${version[0]}.${version[1]}.${version[2]}`; + } + + public static compareBySubminor(v1, v2): number { + return (v1[0] - v2[0] != 0) ? (v1[0] - v2[0]) : (v1[1] - v2[1] != 0) ? v1[1] - v2[1] : v1[2] - v2[2]; + } +} \ No newline at end of file diff --git a/src/adapter/adapterProxy.ts b/src/debug-adapter/adapter/adapterProxy.ts similarity index 96% rename from src/adapter/adapterProxy.ts rename to src/debug-adapter/adapter/adapterProxy.ts index eea8400..e1cd1dc 100644 --- a/src/adapter/adapterProxy.ts +++ b/src/debug-adapter/adapter/adapterProxy.ts @@ -2,9 +2,9 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import * as utils from '../webkit/utilities'; +import * as utils from '../utilities'; import {DebugProtocol} from 'vscode-debugprotocol'; -import {IDebugTransformer, IDebugAdapter} from '../webkit/WebKitAdapterInterfaces'; +import {IDebugTransformer, IDebugAdapter} from '../WebKitAdapterInterfaces'; export type EventHandler = (event: DebugProtocol.Event) => void; diff --git a/src/adapter/lineNumberTransformer.ts b/src/debug-adapter/adapter/lineNumberTransformer.ts similarity index 96% rename from src/adapter/lineNumberTransformer.ts rename to src/debug-adapter/adapter/lineNumberTransformer.ts index 3d5e46a..96439b3 100644 --- a/src/adapter/lineNumberTransformer.ts +++ b/src/debug-adapter/adapter/lineNumberTransformer.ts @@ -3,7 +3,7 @@ *--------------------------------------------------------*/ import {DebugProtocol} from 'vscode-debugprotocol'; -import {IDebugTransformer, ISetBreakpointsResponseBody, IStackTraceResponseBody} from '../webkit/WebKitAdapterInterfaces'; +import {IDebugTransformer, ISetBreakpointsResponseBody, IStackTraceResponseBody} from '../WebKitAdapterInterfaces'; /** * Converts from 1 based lines on the client side to 0 based lines on the target side diff --git a/src/adapter/pathTransformer.ts b/src/debug-adapter/adapter/pathTransformer.ts similarity index 97% rename from src/adapter/pathTransformer.ts rename to src/debug-adapter/adapter/pathTransformer.ts index 198814d..a11a798 100644 --- a/src/adapter/pathTransformer.ts +++ b/src/debug-adapter/adapter/pathTransformer.ts @@ -2,10 +2,10 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import * as utils from '../webkit/utilities'; +import * as utils from '../utilities'; import {DebugProtocol} from 'vscode-debugprotocol'; import * as path from 'path'; -import {ISetBreakpointsArgs, IDebugTransformer, ILaunchRequestArgs, IAttachRequestArgs, IStackTraceResponseBody} from '../webkit/WebKitAdapterInterfaces'; +import {ISetBreakpointsArgs, IDebugTransformer, ILaunchRequestArgs, IAttachRequestArgs, IStackTraceResponseBody} from '../WebKitAdapterInterfaces'; interface IPendingBreakpoint { resolve: () => void; diff --git a/src/adapter/sourceMaps/pathUtilities.ts b/src/debug-adapter/adapter/sourceMaps/pathUtilities.ts similarity index 98% rename from src/adapter/sourceMaps/pathUtilities.ts rename to src/debug-adapter/adapter/sourceMaps/pathUtilities.ts index 6752aaf..411acd6 100644 --- a/src/adapter/sourceMaps/pathUtilities.ts +++ b/src/debug-adapter/adapter/sourceMaps/pathUtilities.ts @@ -7,7 +7,7 @@ import * as Path from 'path'; import * as URL from 'url'; -import * as utils from '../../webkit/utilities'; +import * as utils from '../../utilities'; export function getPathRoot(p: string) { if (p) { diff --git a/src/adapter/sourceMaps/sourceMapTransformer.ts b/src/debug-adapter/adapter/sourceMaps/sourceMapTransformer.ts similarity index 99% rename from src/adapter/sourceMaps/sourceMapTransformer.ts rename to src/debug-adapter/adapter/sourceMaps/sourceMapTransformer.ts index 55cb021..d14e0c6 100644 --- a/src/adapter/sourceMaps/sourceMapTransformer.ts +++ b/src/debug-adapter/adapter/sourceMaps/sourceMapTransformer.ts @@ -6,8 +6,8 @@ import * as path from 'path'; import * as fs from 'fs'; import {DebugProtocol} from 'vscode-debugprotocol'; import {ISourceMaps, SourceMaps} from './sourceMaps'; -import {ISetBreakpointsArgs, IDebugTransformer, ILaunchRequestArgs, IAttachRequestArgs, ISetBreakpointsResponseBody, IStackTraceResponseBody} from '../../webkit/WebKitAdapterInterfaces'; -import * as utils from '../../webkit/utilities'; +import {ISetBreakpointsArgs, IDebugTransformer, ILaunchRequestArgs, IAttachRequestArgs, ISetBreakpointsResponseBody, IStackTraceResponseBody} from '../../WebKitAdapterInterfaces'; +import * as utils from '../../utilities'; interface IPendingBreakpoint { resolve: () => void; diff --git a/src/adapter/sourceMaps/sourceMaps.ts b/src/debug-adapter/adapter/sourceMaps/sourceMaps.ts similarity index 99% rename from src/adapter/sourceMaps/sourceMaps.ts rename to src/debug-adapter/adapter/sourceMaps/sourceMaps.ts index 790cada..d3c1012 100644 --- a/src/adapter/sourceMaps/sourceMaps.ts +++ b/src/debug-adapter/adapter/sourceMaps/sourceMaps.ts @@ -9,8 +9,8 @@ import * as URL from 'url'; import * as FS from 'fs'; import {SourceMapConsumer} from 'source-map'; import * as PathUtils from './pathUtilities'; -import * as utils from '../../webkit/utilities'; -import {Logger} from '../../webkit/utilities'; +import * as utils from '../../utilities'; +import {Logger} from '../../utilities'; export interface MappingResult { diff --git a/src/debug-adapter/connection/INSDebugConnection.ts b/src/debug-adapter/connection/INSDebugConnection.ts new file mode 100644 index 0000000..6e8c138 --- /dev/null +++ b/src/debug-adapter/connection/INSDebugConnection.ts @@ -0,0 +1,29 @@ +export interface INSDebugConnection { + on(eventName: string, handler: (msg: any) => void): void; + + close(): void; + + debugger_setBreakpointByUrl(url: string, lineNumber: number, columnNumber: number, condition?: string): Promise + + debugger_removeBreakpoint(breakpointId: string): Promise + + debugger_stepOver(): Promise; + + debugger_stepIn(): Promise; + + debugger_stepOut(): Promise; + + debugger_resume(): Promise; + + debugger_pause(): Promise; + + debugger_evaluateOnCallFrame(callFrameId: string, expression: string, objectGroup?, returnByValue?: boolean): Promise; + + debugger_setPauseOnExceptions(state: string): Promise; + + debugger_getScriptSource(scriptId: WebKitProtocol.Debugger.ScriptId): Promise; + + runtime_getProperties(objectId: string, ownProperties: boolean, accessorPropertiesOnly: boolean): Promise; + + runtime_evaluate(expression: string, objectGroup?: any, contextId?: number, returnByValue?: boolean): Promise; +} \ No newline at end of file diff --git a/src/nativescript/android/androidDebugConnection.ts b/src/debug-adapter/connection/androidConnection.ts similarity index 96% rename from src/nativescript/android/androidDebugConnection.ts rename to src/debug-adapter/connection/androidConnection.ts index e3d58f0..7016d19 100644 --- a/src/nativescript/android/androidDebugConnection.ts +++ b/src/debug-adapter/connection/androidConnection.ts @@ -1,9 +1,10 @@ import * as http from 'http'; import {EventEmitter} from 'events'; -import * as utils from '../../webkit/utilities'; -import {Logger} from '../../webkit/utilities'; +import * as utils from '../utilities'; +import {Logger} from '../utilities'; import * as Net from 'net'; -import * as ns from '../nativescript' +import * as ns from '../../services/NsCliService'; +import { INSDebugConnection } from './INSDebugConnection'; interface IMessageWithId { @@ -39,7 +40,6 @@ class Callbacks { } - class ResReqNetSocket extends EventEmitter { private _pendingRequests = new Map(); @@ -213,7 +213,7 @@ class ResReqNetSocket extends EventEmitter { } -export class AndroidDebugConnection implements ns.INSDebugConnection { +export class AndroidConnection implements INSDebugConnection { private _nextId = 1; //private _socket: ResReqWebSocket; //private _socket: ResReqHttpSocket; diff --git a/src/webkit/webKitConnection.ts b/src/debug-adapter/connection/iosConnection.ts similarity index 97% rename from src/webkit/webKitConnection.ts rename to src/debug-adapter/connection/iosConnection.ts index d64b99a..8c2ee89 100644 --- a/src/webkit/webKitConnection.ts +++ b/src/debug-adapter/connection/iosConnection.ts @@ -5,9 +5,10 @@ import * as net from 'net'; import * as stream from 'stream'; import {EventEmitter} from 'events'; -import * as utils from './utilities'; -import {Logger} from './utilities'; -import * as ns from '../nativescript/nativescript'; +import {INSDebugConnection} from './INSDebugConnection'; +import * as utils from '../utilities'; +import {Logger} from '../utilities'; +import * as ns from '../../services/NsCliService'; interface IMessageWithId { id: number; @@ -139,7 +140,7 @@ class ResReqTcpSocket extends EventEmitter { /** * Connects to a target supporting the webkit protocol and sends and receives messages */ -export class WebKitConnection implements ns.INSDebugConnection { +export class IosConnection implements INSDebugConnection { private _nextId = 1; private _socket: ResReqTcpSocket; diff --git a/src/webkit/consoleHelper.ts b/src/debug-adapter/consoleHelper.ts similarity index 100% rename from src/webkit/consoleHelper.ts rename to src/debug-adapter/consoleHelper.ts diff --git a/src/webkit/utilities.ts b/src/debug-adapter/utilities.ts similarity index 99% rename from src/webkit/utilities.ts rename to src/debug-adapter/utilities.ts index 5db388c..406e5a1 100644 --- a/src/webkit/utilities.ts +++ b/src/debug-adapter/utilities.ts @@ -2,12 +2,14 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ +// TODO: Some functions can be moved to common. + import * as http from 'http'; import * as os from 'os'; import * as fs from 'fs'; import * as url from 'url'; import * as path from 'path'; -import {ILaunchRequestArgs, IAttachRequestArgs} from '../webkit/WebKitAdapterInterfaces'; +import {ILaunchRequestArgs, IAttachRequestArgs} from './WebKitAdapterInterfaces'; const DEFAULT_CHROME_PATH = { OSX: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', diff --git a/src/webkit/webKitAdapterInterfaces.d.ts b/src/debug-adapter/webKitAdapterInterfaces.d.ts similarity index 100% rename from src/webkit/webKitAdapterInterfaces.d.ts rename to src/debug-adapter/webKitAdapterInterfaces.d.ts diff --git a/src/webkit/webKitDebug.ts b/src/debug-adapter/webKitDebug.ts similarity index 100% rename from src/webkit/webKitDebug.ts rename to src/debug-adapter/webKitDebug.ts diff --git a/src/webkit/webKitDebugAdapter.ts b/src/debug-adapter/webKitDebugAdapter.ts similarity index 97% rename from src/webkit/webKitDebugAdapter.ts rename to src/debug-adapter/webKitDebugAdapter.ts index d325078..be27393 100644 --- a/src/webkit/webKitDebugAdapter.ts +++ b/src/debug-adapter/webKitDebugAdapter.ts @@ -6,11 +6,12 @@ import {spawn, ChildProcess} from 'child_process'; import * as path from 'path'; import {Handles, StoppedEvent, InitializedEvent, TerminatedEvent, OutputEvent} from 'vscode-debugadapter'; import {DebugProtocol} from 'vscode-debugprotocol'; -import {WebKitConnection} from './webKitConnection'; -import {AndroidDebugConnection} from '../nativescript/android/androidDebugConnection'; +import {INSDebugConnection} from './connection/INSDebugConnection'; +import {IosConnection} from './connection/iosConnection'; +import {AndroidConnection} from './connection/androidConnection'; import * as utils from './utilities'; import {formatConsoleMessage} from './consoleHelper'; -import * as ns from '../nativescript/nativescript'; +import * as ns from '../services/NsCliService'; import {ILaunchRequestArgs, IAttachRequestArgs, IDebugAdapter, ISetBreakpointsArgs, ISetBreakpointsResponseBody, IBreakpoint, IStackTraceResponseBody, IScopesResponseBody, IVariablesResponseBody, ISourceResponseBody, IThreadsResponseBody, IEvaluateResponseBody} from './WebKitAdapterInterfaces'; @@ -37,7 +38,7 @@ export class WebKitDebugAdapter implements IDebugAdapter { private _setBreakpointsRequestQ: Promise; private _chromeProc: ChildProcess; - private _webKitConnection: ns.INSDebugConnection; + private _webKitConnection: INSDebugConnection; private _eventHandler: (event: DebugProtocol.Event) => void; private appRoot: string; private platform: string; @@ -136,7 +137,7 @@ export class WebKitDebugAdapter implements IDebugAdapter { return iosProject.debug(args) .then((socketFilePath) => { - let iosConnection: WebKitConnection = new WebKitConnection(); + let iosConnection: IosConnection = new IosConnection(); this.setConnection(iosConnection, args); return iosConnection.attach(socketFilePath); }); @@ -149,7 +150,7 @@ export class WebKitDebugAdapter implements IDebugAdapter { androidProject.on('TNS.outputMessage', (message, level) => thisAdapter.onTnsOutputMessage.apply(thisAdapter, [message, level])); this.onTnsOutputMessage("Getting debug port"); - let androidConnection: AndroidDebugConnection = null; + let androidConnection: AndroidConnection = null; let runDebugCommand: Promise = (args.request == 'launch') ? androidProject.debug(args) : Promise.resolve(); @@ -158,10 +159,8 @@ export class WebKitDebugAdapter implements IDebugAdapter { return androidProject.getDebugPort(args).then(debugPort => { port = debugPort; if (!thisAdapter._webKitConnection) { - return androidProject.createConnection().then(connection => { - androidConnection = connection; - this.setConnection(connection, args); - }); + androidConnection = new AndroidConnection(); + this.setConnection(androidConnection, args); } }).then(() => { this.onTnsOutputMessage("Attaching to debug application"); @@ -170,7 +169,7 @@ export class WebKitDebugAdapter implements IDebugAdapter { }); } - private setConnection(connection: ns.INSDebugConnection, args: IAttachRequestArgs | ILaunchRequestArgs) : ns.INSDebugConnection { + private setConnection(connection: INSDebugConnection, args: IAttachRequestArgs | ILaunchRequestArgs) : INSDebugConnection { connection.on('Debugger.paused', params => this.onDebuggerPaused(params)); connection.on('Debugger.resumed', () => this.onDebuggerResumed()); connection.on('Debugger.scriptParsed', params => this.onScriptParsed(params)); diff --git a/src/webkit/webKitDebugSession.ts b/src/debug-adapter/webKitDebugSession.ts similarity index 94% rename from src/webkit/webKitDebugSession.ts rename to src/debug-adapter/webKitDebugSession.ts index 6ff65e7..7e0d66b 100644 --- a/src/webkit/webKitDebugSession.ts +++ b/src/debug-adapter/webKitDebugSession.ts @@ -7,10 +7,10 @@ import {DebugProtocol} from 'vscode-debugprotocol'; import {WebKitDebugAdapter} from './webKitDebugAdapter'; import {Logger} from './utilities'; -import {AdapterProxy} from '../adapter/adapterProxy'; -import {LineNumberTransformer} from '../adapter/lineNumberTransformer'; -import {PathTransformer} from '../adapter/pathTransformer'; -import {SourceMapTransformer} from '../adapter/sourceMaps/sourceMapTransformer'; +import {AdapterProxy} from './adapter/adapterProxy'; +import {LineNumberTransformer} from './adapter/lineNumberTransformer'; +import {PathTransformer} from './adapter/pathTransformer'; +import {SourceMapTransformer} from './adapter/sourceMaps/sourceMapTransformer'; export class WebKitDebugSession extends DebugSession { private _adapterProxy: AdapterProxy; diff --git a/src/webkit/webKitProtocol.d.ts b/src/debug-adapter/webKitProtocol.d.ts similarity index 100% rename from src/webkit/webKitProtocol.d.ts rename to src/debug-adapter/webKitProtocol.d.ts diff --git a/src/nativescript/nsMain.ts b/src/main.ts similarity index 91% rename from src/nativescript/nsMain.ts rename to src/main.ts index 0b50ee6..a871efe 100644 --- a/src/nativescript/nsMain.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import * as child from 'child_process'; -import * as ns from './nativescript'; +import * as ns from './services/NsCliService'; +import {ExtensionVersionInfo} from './services/ExtensionVersionInfo'; function performVersionsCheck(context: vscode.ExtensionContext) { // Check the state of the existing NativeScript CLI @@ -10,12 +11,12 @@ function performVersionsCheck(context: vscode.ExtensionContext) { } else { // Checks whether a new version of the extension is available - let extensionVersionPromise: Promise = null; + let extensionVersionPromise: Promise = null; // Check the cache for extension version information let extensionVersion: any = context.globalState.get('ExtensionVersionInfo'); if (extensionVersion) { - let extensionVersionInfo = new ns.ExtensionVersionInfo(extensionVersion.latestVersionMetadata, extensionVersion.timestamp); + let extensionVersionInfo = new ExtensionVersionInfo(extensionVersion.latestVersionMetadata, extensionVersion.timestamp); if (extensionVersionInfo.getTimestamp() > Date.now() - 24 * 60 * 60 * 1000 /* Cache the version for a day */) { extensionVersionPromise = Promise.resolve(extensionVersionInfo); } @@ -23,7 +24,7 @@ function performVersionsCheck(context: vscode.ExtensionContext) { if (!extensionVersionPromise) { // Takes the slow path and checks for newer version in the VS Code Marketplace - extensionVersionPromise = ns.ExtensionVersionInfo.createFromMarketplace(); + extensionVersionPromise = ExtensionVersionInfo.createFromMarketplace(); } extensionVersionPromise.then(extensionInfo => { if (extensionInfo) { diff --git a/src/services/ExtensionVersionInfo.ts b/src/services/ExtensionVersionInfo.ts new file mode 100644 index 0000000..67f7c6c --- /dev/null +++ b/src/services/ExtensionVersionInfo.ts @@ -0,0 +1,104 @@ +import {Version} from '../common/Version'; +import * as https from 'https'; + +export class ExtensionVersionInfo { + private static extensionVersion: number[] = null; + private static minNativescriptCliVersion: number[] = null; + private static extensionId: string = '8d837914-d8fa-45b5-965d-f76ebd6dbf5c'; + private static marketplaceQueryResult: Promise = null; + + private latestVersionMeta: any; + private timestamp: number; + + private static initVersionsFromPackageJson() { + let packageJson = require('../../package.json'); + this.extensionVersion = Version.parse(packageJson.version); + this.minNativescriptCliVersion = Version.parse(packageJson.minNativescriptCliVersion); + } + + public static getExtensionVersion(): number[] { + if (this.extensionVersion === null) { + this.initVersionsFromPackageJson(); + } + return this.extensionVersion; + } + + public static getMinSupportedNativeScriptVersion(): number[] { + if (this.minNativescriptCliVersion === null) { + this.initVersionsFromPackageJson(); + } + return this.minNativescriptCliVersion; + } + + public static getMarketplaceExtensionData(): Promise { + if (this.marketplaceQueryResult == null) { + this.marketplaceQueryResult = new Promise((resolve, reject) => { + let postData: string = `{ filters: [{ criteria: [{ filterType: 4, value: "${ExtensionVersionInfo.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', () => { + resolve(JSON.parse(body)); + }); + }); + + request.on('error', (e) => { + reject(e); + }); + + request.end(postData); + }); + } + return this.marketplaceQueryResult; + } + + public static createFromMarketplace(): Promise { + return this.getMarketplaceExtensionData() + .then(marketplaceData => { + let latestVersion = null; + try { + if (marketplaceData.results[0].extensions[0].extensionId == ExtensionVersionInfo.extensionId) { + latestVersion = marketplaceData.results[0].extensions[0].versions[0]; + } + } catch (e) { } + return new ExtensionVersionInfo(latestVersion); + }); + } + + constructor(latestVersionMeta: any, timestamp?: number) { + this.latestVersionMeta = latestVersionMeta; + this.timestamp = timestamp || Date.now(); + } + + public getLatestVersionMeta(): any { + return this.latestVersionMeta; + } + + public isLatest(): boolean { + if (!this.getLatestVersionMeta()) { + return true; + } + return Version.compareBySubminor(ExtensionVersionInfo.getExtensionVersion(), Version.parse(this.getLatestVersionMeta().version)) >= 0; + } + + public getTimestamp(): number { + return this.timestamp; + } +} \ No newline at end of file diff --git a/src/nativescript/nativescript.ts b/src/services/NsCliService.ts similarity index 62% rename from src/nativescript/nativescript.ts rename to src/services/NsCliService.ts index 8df67fa..2d564c7 100644 --- a/src/nativescript/nativescript.ts +++ b/src/services/NsCliService.ts @@ -3,61 +3,96 @@ import * as fs from 'fs'; import {EventEmitter} from 'events'; import * as path from 'path'; import * as https from 'https'; -import {Logger} from '../webkit/utilities'; -import {WebKitConnection} from '../webkit/webKitConnection'; -import {AndroidDebugConnection} from './android/androidDebugConnection'; -import {ILaunchRequestArgs, IAttachRequestArgs} from '../webkit/WebKitAdapterInterfaces'; +import {Version} from '../common/Version'; +import {Logger} from '../debug-adapter/utilities'; +import {ILaunchRequestArgs, IAttachRequestArgs} from '../debug-adapter/WebKitAdapterInterfaces'; +import {ExtensionVersionInfo} from './ExtensionVersionInfo'; -export interface INSDebugConnection { - on(eventName: string, handler: (msg: any) => void): void; - - close(): void; - - debugger_setBreakpointByUrl(url: string, lineNumber: number, columnNumber: number, condition?: string): Promise - - debugger_removeBreakpoint(breakpointId: string): Promise - - debugger_stepOver(): Promise; - - debugger_stepIn(): Promise; +export enum CliVersionState { + NotExisting, + OlderThanSupported, + Compatible +} - debugger_stepOut(): Promise; +export class CliVersionInfo { + private static installedCliVersion: number[] = null; - debugger_resume(): Promise; + private _state: CliVersionState; - debugger_pause(): Promise; + public static getInstalledCliVersion(): number[] { + if (this.installedCliVersion === null) { + // get the currently installed CLI version + let getVersionCommand: string = new CommandBuilder().appendParam('--version').buildAsString(); // tns --version + try { + let versionStr: string = execSync(getVersionCommand).toString().trim(); // execute it + this.installedCliVersion = versionStr ? Version.parse(versionStr) : null; // parse the version string + } catch(e) { + this.installedCliVersion = null; + } + } - debugger_evaluateOnCallFrame(callFrameId: string, expression: string, objectGroup?, returnByValue?: boolean): Promise; + return this.installedCliVersion; + } - debugger_setPauseOnExceptions(state: string): Promise; + constructor() { + let installedCliVersion: number[] = CliVersionInfo.getInstalledCliVersion(); + if (installedCliVersion === null) { + this._state = CliVersionState.NotExisting; + } + else { + let minSupportedCliVersion = ExtensionVersionInfo.getMinSupportedNativeScriptVersion(); + this._state = Version.compareBySubminor(installedCliVersion, minSupportedCliVersion) < 0 ? CliVersionState.OlderThanSupported : CliVersionState.Compatible; + } + } - debugger_getScriptSource(scriptId: WebKitProtocol.Debugger.ScriptId): Promise; + public getState(): CliVersionState { + return this._state; + } - runtime_getProperties(objectId: string, ownProperties: boolean, accessorPropertiesOnly: boolean): Promise; + public isCompatible(): boolean { + return this._state === CliVersionState.Compatible; + } - runtime_evaluate(expression: string, objectGroup?: any, contextId?: number, returnByValue?: boolean): Promise; + public getErrorMessage(): string { + switch (this._state) { + case CliVersionState.NotExisting: + return `NativeScript CLI not found, please run 'npm install –g nativescript' to install it.`; + case CliVersionState.OlderThanSupported: + 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'.`; + default: + return null; + } + } } export abstract class NSProject extends EventEmitter { private _projectPath: string; private _tnsOutputFileStream: fs.WriteStream; + private _cliVersionInfo: CliVersionInfo; constructor(projectPath: string, tnsOutputFilePath?: string) { super(); this._projectPath = projectPath; this._tnsOutputFileStream = tnsOutputFilePath ? fs.createWriteStream(tnsOutputFilePath) : null; + this._cliVersionInfo = new CliVersionInfo(); } - public projectPath(): string { + public getProjectPath(): string { return this._projectPath; } + public getCliVersionInfo() { + return this._cliVersionInfo; + } + public abstract platform(): string; public abstract run(emulator: boolean): Promise; + public abstract debug(args: IAttachRequestArgs | ILaunchRequestArgs): Promise; + protected spawnProcess(commandPath: string, commandArgs: string[], tnsOutput?: string): ChildProcess { - let child: ChildProcess = spawn(commandPath, commandArgs, { cwd: this.projectPath() }); + let child: ChildProcess = spawn(commandPath, commandArgs, { cwd: this.getProjectPath() }); child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); return child; @@ -219,10 +254,6 @@ export class AndroidProject extends NSProject { } } - public createConnection(): Promise { - return Promise.resolve(new AndroidDebugConnection()); - } - public getDebugPort(args: IAttachRequestArgs | ILaunchRequestArgs): Promise { //TODO: Call CLI to get the debug port //return Promise.resolve(40001); @@ -309,184 +340,4 @@ class CommandBuilder { let result = this.build(); return `${result.path} ` + result.args.join(' '); } -} - -class Version { - public static parse(versionStr: string): number[] { - if (versionStr === null) { - return null; - } - let version: number[] = versionStr.split('.').map((str, index, array) => parseInt(str)); - for(let i = version.length; i < 3; i++) { - version.push(0); - } - return version; - } - - public static stringify(version: number[]): string { - return `${version[0]}.${version[1]}.${version[2]}`; - } - - public static compareBySubminor(v1, v2): number { - return (v1[0] - v2[0] != 0) ? (v1[0] - v2[0]) : (v1[1] - v2[1] != 0) ? v1[1] - v2[1] : v1[2] - v2[2]; - } -} - -export class ExtensionVersionInfo { - private static extensionVersion: number[] = null; - private static minNativescriptCliVersion: number[] = null; - private static extensionId: string = '8d837914-d8fa-45b5-965d-f76ebd6dbf5c'; - private static marketplaceQueryResult: Promise = null; - - private latestVersionMeta: any; - private timestamp: number; - - private static initVersionsFromPackageJson() { - let packageJson = require('../../package.json'); - this.extensionVersion = Version.parse(packageJson.version); - this.minNativescriptCliVersion = Version.parse(packageJson.minNativescriptCliVersion); - } - - public static getExtensionVersion(): number[] { - if (this.extensionVersion === null) { - this.initVersionsFromPackageJson(); - } - return this.extensionVersion; - } - - public static getMinSupportedNativeScriptVersion(): number[] { - if (this.minNativescriptCliVersion === null) { - this.initVersionsFromPackageJson(); - } - return this.minNativescriptCliVersion; - } - - public static getMarketplaceExtensionData(): Promise { - if (this.marketplaceQueryResult == null) { - this.marketplaceQueryResult = new Promise((resolve, reject) => { - let postData: string = `{ filters: [{ criteria: [{ filterType: 4, value: "${ExtensionVersionInfo.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', () => { - resolve(JSON.parse(body)); - }); - }); - - request.on('error', (e) => { - reject(e); - }); - - request.end(postData); - }); - } - return this.marketplaceQueryResult; - } - - public static createFromMarketplace(): Promise { - return this.getMarketplaceExtensionData() - .then(marketplaceData => { - let latestVersion = null; - try { - if (marketplaceData.results[0].extensions[0].extensionId == ExtensionVersionInfo.extensionId) { - latestVersion = marketplaceData.results[0].extensions[0].versions[0]; - } - } catch (e) { } - return new ExtensionVersionInfo(latestVersion); - }); - } - - constructor(latestVersionMeta: any, timestamp?: number) { - this.latestVersionMeta = latestVersionMeta; - this.timestamp = timestamp || Date.now(); - } - - public getLatestVersionMeta(): any { - return this.latestVersionMeta; - } - - public isLatest(): boolean { - if (!this.getLatestVersionMeta()) { - return true; - } - return Version.compareBySubminor(ExtensionVersionInfo.getExtensionVersion(), Version.parse(this.getLatestVersionMeta().version)) >= 0; - } - - public getTimestamp(): number { - return this.timestamp; - } -} - -export enum CliState { - NotExisting, - OlderThanSupported, - Compatible -} - -export class CliVersionInfo { - private static installedCliVersion: number[] = null; - - private _state: CliState; - - public static getInstalledCliVersion(): number[] { - if (this.installedCliVersion === null) { - // get the currently installed CLI version - let getVersionCommand: string = new CommandBuilder().appendParam('--version').buildAsString(); // tns --version - try { - let versionStr: string = execSync(getVersionCommand).toString().trim(); // execute it - this.installedCliVersion = versionStr ? Version.parse(versionStr) : null; // parse the version string - } catch(e) { - this.installedCliVersion = null; - } - } - - return this.installedCliVersion; - } - - constructor() { - let installedCliVersion: number[] = CliVersionInfo.getInstalledCliVersion(); - if (installedCliVersion === null) { - this._state = CliState.NotExisting; - } - else { - let minSupportedCliVersion = ExtensionVersionInfo.getMinSupportedNativeScriptVersion(); - this._state = Version.compareBySubminor(installedCliVersion, minSupportedCliVersion) < 0 ? CliState.OlderThanSupported : CliState.Compatible; - } - } - - public getState(): CliState { - return this._state; - } - - public isCompatible(): boolean { - return this._state === CliState.Compatible; - } - - public getErrorMessage(): string { - switch (this._state) { - case CliState.NotExisting: - return `NativeScript CLI not found, please run 'npm install –g nativescript' to install it.`; - case CliState.OlderThanSupported: - 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'.`; - default: - return null; - } - } } \ No newline at end of file diff --git a/src/tsconfig.json b/src/tsconfig.json index 2679985..841687e 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -13,10 +13,10 @@ // typescript definitions "typings/main.d.ts", "custom-typings/es6-impl/es6-impl.d.ts", - "webkit/webKitProtocol.d.ts", + "debug-adapter/webKitProtocol.d.ts", - "./webkit/webKitDebug.ts", - "./nativescript/nsMain.ts", + "./debug-adapter/webKitDebug.ts", + "./main.ts", "./tests/adapter.test.ts" ] } \ No newline at end of file From bc0a3e6b70db0db9542752bc9bfccd05adba376a Mon Sep 17 00:00:00 2001 From: ivanbuhov Date: Mon, 6 Jun 2016 15:51:06 +0300 Subject: [PATCH 2/6] update typings --- package.json | 2 +- src/tsconfig.json | 2 +- src/typings.json | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 88cc45b..9cb54ee 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "mocha": "^2.4.5", "tslint": "^3.5.0", "typescript": "^1.8.2", - "typings": "^0.7.9", + "typings": "^1.0.4", "vsce": "^1.0.0", "vscode": "^0.11.x", "vscode-debugadapter-testsupport": "^1.7.0" diff --git a/src/tsconfig.json b/src/tsconfig.json index 841687e..fe20bb9 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -11,7 +11,7 @@ }, "files": [ // typescript definitions - "typings/main.d.ts", + "typings/index.d.ts", "custom-typings/es6-impl/es6-impl.d.ts", "debug-adapter/webKitProtocol.d.ts", diff --git a/src/typings.json b/src/typings.json index f0c8a41..ecf3a14 100644 --- a/src/typings.json +++ b/src/typings.json @@ -1,11 +1,14 @@ { "name": "nativescript", "version": false, - "ambientDependencies": { + "globalDependencies": { "es6-collections": "github:DefinitelyTyped/DefinitelyTyped/es6-collections/es6-collections.d.ts#81b951f1ac437d1eb5ff5171a0bfa6c467634b13", "es6-promise": "github:DefinitelyTyped/DefinitelyTyped/es6-promise/es6-promise.d.ts#81b951f1ac437d1eb5ff5171a0bfa6c467634b13", - "mocha": "registry:dt/mocha#2.2.5+20160317120654", "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#8ea42cd8bb11863ed6f242d67c502288ebc45a7b", "source-map": "github:DefinitelyTyped/DefinitelyTyped/source-map/source-map.d.ts#bb45306d0fd8ce0852a8d24c023fd787f4151e65" + }, + "globalDevDependencies": { + "mocha": "registry:dt/mocha#2.2.5+20160317120654" + }, } } From 008e04da6ea8ed7fcce2ed64dd2503cf8da2624e Mon Sep 17 00:00:00 2001 From: ivanbuhov Date: Mon, 13 Jun 2016 12:55:51 +0300 Subject: [PATCH 3/6] Add Google Analytics tracking --- package.json | 7 ++- src/.vscode/launch.json | 4 +- src/debug-adapter/webKitDebugAdapter.ts | 2 + src/main.ts | 4 +- src/services/analytics/AnalyticsBaseInfo.ts | 14 +++++ src/services/analytics/AnalyticsService.ts | 67 +++++++++++++++++++++ src/services/analytics/GUAService.ts | 45 ++++++++++++++ src/typings.json | 2 + 8 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/services/analytics/AnalyticsBaseInfo.ts create mode 100644 src/services/analytics/AnalyticsService.ts create mode 100644 src/services/analytics/GUAService.ts diff --git a/package.json b/package.json index 9cb54ee..5fe95ac 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,9 @@ "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "source-map": "^0.5.3", - "vscode-debugprotocol": "^1.7.0", - "vscode-debugadapter": "^1.7.0" + "universal-analytics": "^0.3.11", + "vscode-debugadapter": "^1.7.0", + "vscode-debugprotocol": "^1.7.0" }, "devDependencies": { "mocha": "^2.4.5", @@ -87,7 +88,7 @@ "typescript" ] }, - "program": "./out/webkit/webKitDebug.js", + "program": "./out/debug-adapter/webKitDebug.js", "runtime": "node", "initialConfigurations": [ { diff --git a/src/.vscode/launch.json b/src/.vscode/launch.json index 099c73c..30dcafb 100644 --- a/src/.vscode/launch.json +++ b/src/.vscode/launch.json @@ -5,7 +5,7 @@ "name": "launch as server", "type": "node", "request": "launch", - "program": "${workspaceRoot}/../out/webkit/webKitDebug.js", + "program": "${workspaceRoot}/../out/debug-adapter/webKitDebug.js", "runtimeArgs": ["--nolazy"], "args": [ "--server=4712" ], "stopOnEntry": true, @@ -20,7 +20,7 @@ // Path to VSCode executable "runtimeExecutable": "${execPath}", "args": [ - "--extensionDevelopmentPath=${workspaceRoot}" + "--extensionDevelopmentPath=${workspaceRoot}/.." ], "stopOnEntry": false, "sourceMaps": true, diff --git a/src/debug-adapter/webKitDebugAdapter.ts b/src/debug-adapter/webKitDebugAdapter.ts index be27393..66e0331 100644 --- a/src/debug-adapter/webKitDebugAdapter.ts +++ b/src/debug-adapter/webKitDebugAdapter.ts @@ -14,6 +14,7 @@ import {formatConsoleMessage} from './consoleHelper'; import * as ns from '../services/NsCliService'; import {ILaunchRequestArgs, IAttachRequestArgs, IDebugAdapter, ISetBreakpointsArgs, ISetBreakpointsResponseBody, IBreakpoint, IStackTraceResponseBody, IScopesResponseBody, IVariablesResponseBody, ISourceResponseBody, IThreadsResponseBody, IEvaluateResponseBody} from './WebKitAdapterInterfaces'; +import {AnalyticsService} from '../services/analytics/AnalyticsService'; interface IScopeVarHandle { @@ -114,6 +115,7 @@ export class WebKitDebugAdapter implements IDebugAdapter { } private _attach(args: IAttachRequestArgs | ILaunchRequestArgs) { + AnalyticsService.getInstance().launchDebugger(args.request, args.platform, args.emulator); this.initDiagnosticLogging(args.request, args); this.appRoot = utils.getAppRoot(args); this.platform = args.platform; diff --git a/src/main.ts b/src/main.ts index a871efe..72b2f37 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,7 @@ import * as vscode from 'vscode'; import * as child from 'child_process'; import * as ns from './services/NsCliService'; import {ExtensionVersionInfo} from './services/ExtensionVersionInfo'; +import {AnalyticsService} from './services/analytics/AnalyticsService'; function performVersionsCheck(context: vscode.ExtensionContext) { // Check the state of the existing NativeScript CLI @@ -37,7 +38,7 @@ function performVersionsCheck(context: vscode.ExtensionContext) { } } -// this method is called when your extension is activated +// this method is called when the extension is activated export function activate(context: vscode.ExtensionContext) { performVersionsCheck(context); @@ -64,6 +65,7 @@ export function activate(context: vscode.ExtensionContext) { // Execute run command let emulator: boolean = (target === 'emulator'); + AnalyticsService.getInstance().runRunCommand(project.platform(), emulator); return project.run(emulator) .then(tnsProcess => { tnsProcess.on('error', err => { diff --git a/src/services/analytics/AnalyticsBaseInfo.ts b/src/services/analytics/AnalyticsBaseInfo.ts new file mode 100644 index 0000000..4201928 --- /dev/null +++ b/src/services/analytics/AnalyticsBaseInfo.ts @@ -0,0 +1,14 @@ +export enum OperatingSystem { + Windows, + Linux, + OSX, + Other +} + +export interface AnalyticsBaseInfo { + operatingSystem: OperatingSystem, + cliVersion: string, + extensionVersion: string, + userId: string, + hostname: string +} \ No newline at end of file diff --git a/src/services/analytics/AnalyticsService.ts b/src/services/analytics/AnalyticsService.ts new file mode 100644 index 0000000..d6f13d7 --- /dev/null +++ b/src/services/analytics/AnalyticsService.ts @@ -0,0 +1,67 @@ +import * as os from 'os'; +import { Version } from '../../common/Version'; +import { GUAService } from './GUAService'; +import { AnalyticsBaseInfo, OperatingSystem } from './AnalyticsBaseInfo'; +import { ExtensionVersionInfo } from '../ExtensionVersionInfo'; +import * as ns from '../NsCliService'; + +export class AnalyticsService { + private static _instance: AnalyticsService; + + private _baseInfo: AnalyticsBaseInfo; + private _gua: GUAService; + + public static getInstance(): AnalyticsService { + if (!this._instance) { + this._instance = new AnalyticsService(); + } + return this._instance; + } + + public static generateMachineId(): string { + let machineId = ''; + try { + let netInterfaces = os.networkInterfaces(); + Object.keys(netInterfaces).forEach(interfName => { + netInterfaces[interfName].forEach(interf => { + if (!interf.internal) { + machineId += `${interf.mac}-`; + } + }); + }); + } catch(e) {} + return machineId; + } + + constructor() { + let operatingSystem = OperatingSystem.Other; + switch(process.platform) { + case 'win32': { operatingSystem = OperatingSystem.Windows; break; } + case 'darwin': { operatingSystem = OperatingSystem.OSX; break; } + case 'linux': + case 'freebsd': { operatingSystem = OperatingSystem.Linux; break; } + }; + + this._baseInfo = { + cliVersion: Version.stringify(ns.CliVersionInfo.getInstalledCliVersion()), + extensionVersion: Version.stringify(ExtensionVersionInfo.getExtensionVersion()), + operatingSystem: operatingSystem, + userId: AnalyticsService.generateMachineId(), + hostname: 'ns-vs-extension.org' + }; + + this._gua = new GUAService('UA-111455-29', this._baseInfo); + } + + public launchDebugger(request: string, platform: string, emulator: boolean): Promise { + try { + return this._gua.launchDebugger(request, platform, emulator); + } catch(e) {} + } + + public runRunCommand(platform: string, emulator: boolean): Promise { + try { + return this._gua.runRunCommand(platform, emulator); + } catch(e) {} + } +} \ No newline at end of file diff --git a/src/services/analytics/GUAService.ts b/src/services/analytics/GUAService.ts new file mode 100644 index 0000000..ed6ca31 --- /dev/null +++ b/src/services/analytics/GUAService.ts @@ -0,0 +1,45 @@ +import * as ua from 'universal-analytics'; +import { AnalyticsBaseInfo, OperatingSystem } from './AnalyticsBaseInfo'; + +/** + * Google Universal Analytics Service + */ +export class GUAService { + private _visitor: any; + private _getBasePayload: () => any; + + constructor(trackingId: string, baseInfo: AnalyticsBaseInfo) { + this._visitor = ua(trackingId); + this._getBasePayload = () => { + return { + uid: baseInfo.userId, + dh: baseInfo.hostname, + cd5: baseInfo.cliVersion, + cd6: OperatingSystem[baseInfo.operatingSystem], + cd7: baseInfo.extensionVersion + }; + }; + } + + public launchDebugger(request: string, platform: string, emulator: boolean): Promise { + let payload = this._getBasePayload(); + payload.ec = 'vscode-extension-debug'; // event category + payload.ea = `debug-${request}-on-${platform}-${emulator ? 'emulator' : 'device'}`; // event action + return this.sendEvent(payload); + } + + public runRunCommand(platform: string, emulator: boolean): Promise { + let payload = this._getBasePayload(); + payload.ec = 'vscode-extension-command'; // event category + payload.ea = `command-run-on-${platform}-${emulator ? 'emulator' : 'device'}`; // event action + return this.sendEvent(payload); + } + + private sendEvent(params): Promise { + return new Promise((res, rej) => { + this._visitor.event(params, err => { + return err ? rej(err) : res(); + }); + }); + } +} \ No newline at end of file diff --git a/src/typings.json b/src/typings.json index ecf3a14..9996450 100644 --- a/src/typings.json +++ b/src/typings.json @@ -10,5 +10,7 @@ "globalDevDependencies": { "mocha": "registry:dt/mocha#2.2.5+20160317120654" }, + "dependencies": { + "universal-analytics": "registry:npm/universal-analytics#0.3.10+20160419033917" } } From 4714c6ff87c526beb5c2e74b5f21556c275f3692 Mon Sep 17 00:00:00 2001 From: ivanbuhov Date: Wed, 15 Jun 2016 10:34:53 +0300 Subject: [PATCH 4/6] Add interprocess communication between debug adapter and extension host --- package.json | 1 + src/debug-adapter/webKitDebugAdapter.ts | 5 +- src/main.ts | 6 +++ src/services/ipc/ExtensionClient.ts | 71 +++++++++++++++++++++++++ src/services/ipc/ExtensionProtocol.ts | 21 ++++++++ src/services/ipc/ExtensionServer.ts | 71 +++++++++++++++++++++++++ 6 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 src/services/ipc/ExtensionClient.ts create mode 100644 src/services/ipc/ExtensionProtocol.ts create mode 100644 src/services/ipc/ExtensionServer.ts diff --git a/package.json b/package.json index 5fe95ac..603bf11 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ ], "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { + "node-ipc": "^7.0.0", "source-map": "^0.5.3", "universal-analytics": "^0.3.11", "vscode-debugadapter": "^1.7.0", diff --git a/src/debug-adapter/webKitDebugAdapter.ts b/src/debug-adapter/webKitDebugAdapter.ts index 66e0331..61ce2bb 100644 --- a/src/debug-adapter/webKitDebugAdapter.ts +++ b/src/debug-adapter/webKitDebugAdapter.ts @@ -15,7 +15,7 @@ import * as ns from '../services/NsCliService'; import {ILaunchRequestArgs, IAttachRequestArgs, IDebugAdapter, ISetBreakpointsArgs, ISetBreakpointsResponseBody, IBreakpoint, IStackTraceResponseBody, IScopesResponseBody, IVariablesResponseBody, ISourceResponseBody, IThreadsResponseBody, IEvaluateResponseBody} from './WebKitAdapterInterfaces'; import {AnalyticsService} from '../services/analytics/AnalyticsService'; - +import {ExtensionClient} from '../services/ipc/ExtensionClient'; interface IScopeVarHandle { objectId: string; @@ -115,7 +115,8 @@ export class WebKitDebugAdapter implements IDebugAdapter { } private _attach(args: IAttachRequestArgs | ILaunchRequestArgs) { - AnalyticsService.getInstance().launchDebugger(args.request, args.platform, args.emulator); + ExtensionClient.setAppRoot(utils.getAppRoot(args)); + ExtensionClient.getInstance().analyticsLaunchDebugger({ request: args.request, platform: args.platform, emulator: args.emulator }); this.initDiagnosticLogging(args.request, args); this.appRoot = utils.getAppRoot(args); this.platform = args.platform; diff --git a/src/main.ts b/src/main.ts index 72b2f37..b25ffaa 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import * as child from 'child_process'; import * as ns from './services/NsCliService'; import {ExtensionVersionInfo} from './services/ExtensionVersionInfo'; import {AnalyticsService} from './services/analytics/AnalyticsService'; +import {ExtensionServer} from './services/ipc/ExtensionServer'; function performVersionsCheck(context: vscode.ExtensionContext) { // Check the state of the existing NativeScript CLI @@ -40,6 +41,7 @@ function performVersionsCheck(context: vscode.ExtensionContext) { // this method is called when the extension is activated export function activate(context: vscode.ExtensionContext) { + ExtensionServer.getInstance().start(); performVersionsCheck(context); let runCommand = (project: ns.NSProject, options: string[]) => { @@ -100,4 +102,8 @@ export function activate(context: vscode.ExtensionContext) { context.subscriptions.push(runIosCommand); context.subscriptions.push(runAndroidCommand); +} + +export function deactivate() { + ExtensionServer.getInstance().stop(); } \ No newline at end of file diff --git a/src/services/ipc/ExtensionClient.ts b/src/services/ipc/ExtensionClient.ts new file mode 100644 index 0000000..028d287 --- /dev/null +++ b/src/services/ipc/ExtensionClient.ts @@ -0,0 +1,71 @@ +import * as path from 'path'; +import * as extProtocol from './ExtensionProtocol'; +let ipc = require('node-ipc'); + +export class ExtensionClient { + private static _appRoot: string; + private static _instance: ExtensionClient; + + private _idCounter = 0; + private _pendingRequests: Object; + + private _ipcClientInitialized: Promise; + + public static getInstance() { + if (!this._instance) { + this._instance = new ExtensionClient(); + } + return this._instance; + } + + public static getAppRoot() { + return this._appRoot; + } + + public static setAppRoot(appRoot: string) { + this._appRoot = appRoot; + } + + constructor() { + if (!ExtensionClient.getAppRoot()) { + throw new Error(`Unable to connect to extension host. App root is '${ExtensionClient.getAppRoot()}'`); + } + + this._idCounter = 0; + this._pendingRequests = {}; + + ipc.config.id = 'debug-adpater-' + process.pid; + ipc.config.retry = 1500; + + this._ipcClientInitialized = new Promise((res, rej) => { + ipc.connectTo( + 'extHost', + path.join(ExtensionClient.getAppRoot(), 'temp-nativescript-vscode-extension-pipe-handle'), + () => { + ipc.of.extHost.on('connect', () => { + res(); + }); + ipc.of.extHost.on('extension-protocol-message', (response: extProtocol.Response) => { + (<(result: Object) => void>this._pendingRequests[response.requestId])(response.result); + }); + } + ); + }); + } + + private callRemoteMethod(method: string, args: Object): Promise { + let request: extProtocol.Request = { id: 'req' + (++this._idCounter), method: method, args: args }; + return new Promise((res, rej) => { + this._pendingRequests[request.id] = res; + ipc.of.extHost.emit('extension-protocol-message', request); + }); + } + + public analyticsLaunchDebugger(args: extProtocol.AnalyticsLaunchDebuggerArgs): Promise { + return this.callRemoteMethod('analyticsLaunchDebugger', args); + } + + public runRunCommand(args: extProtocol.AnalyticsRunRunCommandArgs): Promise { + return this.callRemoteMethod('runRunCommand', args); + } +} \ No newline at end of file diff --git a/src/services/ipc/ExtensionProtocol.ts b/src/services/ipc/ExtensionProtocol.ts new file mode 100644 index 0000000..c7be9f1 --- /dev/null +++ b/src/services/ipc/ExtensionProtocol.ts @@ -0,0 +1,21 @@ +export interface Request { + id: string; + method: string; + args: Object; +} + +export interface Response { + requestId: string; + result: Object; +} + +export interface AnalyticsLaunchDebuggerArgs { + request: string; + platform: string; + emulator: boolean; +} + +export interface AnalyticsRunRunCommandArgs { + platform: string; + emulator: boolean; +} \ No newline at end of file diff --git a/src/services/ipc/ExtensionServer.ts b/src/services/ipc/ExtensionServer.ts new file mode 100644 index 0000000..faa7cf3 --- /dev/null +++ b/src/services/ipc/ExtensionServer.ts @@ -0,0 +1,71 @@ +import * as path from 'path'; +import * as fs from 'fs'; +import * as vscode from 'vscode'; +import * as extProtocol from './ExtensionProtocol'; +import {AnalyticsService} from '../analytics/AnalyticsService'; +let ipc = require('node-ipc'); + +export class ExtensionServer { + private static _instance: ExtensionServer; + + private _isRunning: boolean; + + public static getInstance() { + if (!this._instance) { + this._instance = new ExtensionServer(); + } + return this._instance; + } + + constructor() { + this._isRunning = false; + } + + public getPipeHandlePath(): string { + return vscode.workspace.rootPath ? + path.join(vscode.workspace.rootPath, 'temp-nativescript-vscode-extension-pipe-handle') : + null; + } + + public start() { + if (!this._isRunning) { + let pipeHandlePath = this.getPipeHandlePath(); + if (pipeHandlePath) { + ipc.serve( + pipeHandlePath, + () => { + ipc.server.on('extension-protocol-message', (data: extProtocol.Request, socket) => { + return (>this[data.method].call(this, data.args)).then(result => { + let response: extProtocol.Response = { requestId: data.id, result: result }; + return ipc.server.emit(socket, 'extension-protocol-message', response); + }); + }); + }); + ipc.server.start(); + this._isRunning = true; + } + } + return this._isRunning; + } + + public stop() { + if (this._isRunning) { + ipc.server.stop(); + this._isRunning = false; + } + } + + public isRunning() { + return this._isRunning; + } + + public analyticsLaunchDebugger(args: extProtocol.AnalyticsLaunchDebuggerArgs): Promise { + return AnalyticsService.getInstance().launchDebugger(args.request, args.platform, args.emulator); + } + + public runRunCommand(args: extProtocol.AnalyticsRunRunCommandArgs): Promise { + return AnalyticsService.getInstance().runRunCommand(args.platform, args.emulator); + } + + +} \ No newline at end of file From 8dc5d0fd36acc70f9a7c1ccac343932d4e6e98a3 Mon Sep 17 00:00:00 2001 From: ivanbuhov Date: Wed, 15 Jun 2016 13:58:54 +0300 Subject: [PATCH 5/6] Make the root folder a vscode project too --- .vscode/launch.json | 79 +++++++++++++++++++++++++++++++++++++++++++ .vscode/settings.json | 15 ++++++++ .vscode/tasks.json | 10 ++++++ 3 files changed, 104 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2793526 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,79 @@ +{ + "version": "0.1.0", + "configurations": [ + { + "name": "launch as server", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/out/debug-adapter/webKitDebug.js", + "runtimeArgs": ["--nolazy"], + "args": [ "--server=4712" ], + "stopOnEntry": false, + "sourceMaps": true, + "outDir": "${workspaceRoot}/out", + "cwd": "${workspaceRoot}" + }, + { + "name": "launch in extension host", + "type": "extensionHost", + "request": "launch", + // Path to VSCode executable + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceRoot}" + ], + "stopOnEntry": true, + "sourceMaps": true, + "outDir": "${workspaceRoot}/out", + "cwd": "${workspaceRoot}" + }, + { + "name": "run tests on mac", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "runtimeArgs": [ "--nolazy" ], + "args": [ + "--opts", "${workspaceRoot}/src/tests/config/mocha.opts", + "--config", "${workspaceRoot}/src/tests/config/mac.json", + "${workspaceRoot}/out/tests/" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outDir": "${workspaceRoot}/out", + "cwd": "${workspaceRoot}" + }, + { + "name": "run tests on win", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "runtimeArgs": [ "--nolazy" ], + "args": [ + "--opts", "${workspaceRoot}/src/tests/config/mocha.opts", + "--config", "${workspaceRoot}/src/tests/config/win.json", + "${workspaceRoot}/out/tests/" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outDir": "${workspaceRoot}/out", + "cwd": "${workspaceRoot}" + }, + { + "name": "run tests (custom)", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "runtimeArgs": [ "--nolazy" ], + "args": [ + "--opts", "${workspaceRoot}/src/tests/config/mocha.opts", + "--config", "${workspaceRoot}/src/tests/config/custom.json", + "${workspaceRoot}/out/tests/" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outDir": "${workspaceRoot}/out", + "cwd": "${workspaceRoot}" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7c3a67a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "editor.insertSpaces": true, + "files.trimTrailingWhitespace": true, + "files.exclude": { + ".git": true, + "bin": true, + "node_modules": false + }, + "search.exclude": { + ".git": true, + "node_modules": true, + "bin": true, + "out": true + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ade836c --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,10 @@ +{ + "version": "0.1.0", + "windows": { + "command": ".\\node_modules\\.bin\\tsc" + }, + "command": "./node_modules/.bin/tsc", + "isShellCommand": true, + "args": ["-p", "./src"], + "problemMatcher": "$tsc" +} \ No newline at end of file From f62d0bc31e624dbf4283035c384082ca96a5a22a Mon Sep 17 00:00:00 2001 From: ivanbuhov Date: Thu, 30 Jun 2016 17:46:58 +0300 Subject: [PATCH 6/6] Implement Telerik Analytics tracking --- package.json | 14 +++- src/services/analytics/AnalyticsBaseInfo.ts | 3 +- src/services/analytics/AnalyticsService.ts | 37 +++++++--- src/services/analytics/EqatecMonitor.min.js | 30 ++++++++ src/services/analytics/GUAService.ts | 4 +- .../analytics/TelerikAnalyticsService.ts | 70 +++++++++++++++++++ src/services/ipc/ExtensionServer.ts | 2 - 7 files changed, 144 insertions(+), 16 deletions(-) create mode 100755 src/services/analytics/EqatecMonitor.min.js create mode 100644 src/services/analytics/TelerikAnalyticsService.ts diff --git a/package.json b/package.json index 603bf11..ff967d2 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "dependencies": { "node-ipc": "^7.0.0", "source-map": "^0.5.3", + "xmlhttprequest": "https://github.com/telerik/node-XMLHttpRequest/tarball/master", "universal-analytics": "^0.3.11", "vscode-debugadapter": "^1.7.0", "vscode-debugprotocol": "^1.7.0" @@ -43,7 +44,7 @@ "scripts": { "postinstall": "node ./node_modules/vscode/bin/install && cd src && typings install", "clean": "git clean -fdx", - "build": "tsc -p ./src", + "build": "tsc -p ./src && cp ./src/services/analytics/EqatecMonitor.min.js ./out/services/analytics/EqatecMonitor.min.js", "package": "vsce package", "launch-as-server": "node --nolazy ./out/webkit/webKitDebug.js --server=4712", "test-mac": "mocha --opts ./src/tests/config/mocha.opts --config ../../src/tests/config/mac.json ./out/tests", @@ -55,6 +56,17 @@ "*" ], "contributes": { + "configuration": { + "type": "object", + "title": "NativeScript Extension Configurations", + "properties": { + "nativescript.analytics.enabled": { + "type": "boolean", + "default": true, + "description": "Enables the extension tracking." + } + } + }, "commands": [ { "command": "nativescript.runIos", diff --git a/src/services/analytics/AnalyticsBaseInfo.ts b/src/services/analytics/AnalyticsBaseInfo.ts index 4201928..5098a67 100644 --- a/src/services/analytics/AnalyticsBaseInfo.ts +++ b/src/services/analytics/AnalyticsBaseInfo.ts @@ -9,6 +9,5 @@ export interface AnalyticsBaseInfo { operatingSystem: OperatingSystem, cliVersion: string, extensionVersion: string, - userId: string, - hostname: string + userId: string } \ No newline at end of file diff --git a/src/services/analytics/AnalyticsService.ts b/src/services/analytics/AnalyticsService.ts index d6f13d7..a06aa1d 100644 --- a/src/services/analytics/AnalyticsService.ts +++ b/src/services/analytics/AnalyticsService.ts @@ -1,6 +1,8 @@ import * as os from 'os'; +import * as vscode from 'vscode'; 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'; @@ -10,6 +12,8 @@ export class AnalyticsService { private _baseInfo: AnalyticsBaseInfo; private _gua: GUAService; + private _ta: TelerikAnalyticsService; + private _analyticsEnabled: boolean; public static getInstance(): AnalyticsService { if (!this._instance) { @@ -34,6 +38,7 @@ export class AnalyticsService { } constructor() { + this._analyticsEnabled = vscode.workspace.getConfiguration('nativescript').get('analytics.enabled') as boolean; let operatingSystem = OperatingSystem.Other; switch(process.platform) { case 'win32': { operatingSystem = OperatingSystem.Windows; break; } @@ -46,22 +51,36 @@ export class AnalyticsService { cliVersion: Version.stringify(ns.CliVersionInfo.getInstalledCliVersion()), extensionVersion: Version.stringify(ExtensionVersionInfo.getExtensionVersion()), operatingSystem: operatingSystem, - userId: AnalyticsService.generateMachineId(), - hostname: 'ns-vs-extension.org' + userId: AnalyticsService.generateMachineId() }; - this._gua = new GUAService('UA-111455-29', this._baseInfo); + if(this._analyticsEnabled) { + this._gua = new GUAService('UA-111455-29', this._baseInfo); + this._ta = new TelerikAnalyticsService('b8b2e51f188f43e9b0dfb899f7b71cc6', this._baseInfo); + } } public launchDebugger(request: string, platform: string, emulator: boolean): Promise { - try { - return this._gua.launchDebugger(request, platform, emulator); - } catch(e) {} + if(this._analyticsEnabled) { + try { + return Promise.all([ + this._gua.launchDebugger(request, platform, emulator), + this._ta.launchDebugger(request, platform, emulator) + ]); + } catch(e) {} + } + return Promise.resolve(); } public runRunCommand(platform: string, emulator: boolean): Promise { - try { - return this._gua.runRunCommand(platform, emulator); - } catch(e) {} + if(this._analyticsEnabled) { + try { + return Promise.all([ + this._gua.runRunCommand(platform, emulator), + this._ta.runRunCommand(platform, emulator) + ]); + } catch(e) {} + } + return Promise.resolve(); } } \ No newline at end of file diff --git a/src/services/analytics/EqatecMonitor.min.js b/src/services/analytics/EqatecMonitor.min.js new file mode 100755 index 0000000..f87f322 --- /dev/null +++ b/src/services/analytics/EqatecMonitor.min.js @@ -0,0 +1,30 @@ +(function(k){function z(b){var a=!1,f="",e=0,d=1,g={},h=[],i=[],l=function(a){if(c.isString(a)){var f=c.trim(c.asString(a));if(f){if(c.stringTooLong(b,f,1E3))return null;var a="eq_"+a,e=g[a];e||(e={featureName:f,sessionHitCount:0,timingStart:0},g[a]=e);return e}return null}};return{addFeatureUsage:function(a){if(a=l(a))a.sessionHitCount+=1,d++},startFeatureTiming:function(a){if((a=l(a))&&!(0b++;a+=51*b&52?(b^15?8^Math.random()*(b^20?16:4):4).toString(16):"-");return a},setCookie:function(b,a,f,e,d){var g=document;g&&(b=b+"="+a+";path="+f+";",e&&0f?(c.error(b,"Input is too long: "+a),!0):!1}};(function(){function b(a){return 10>a?"0"+a:a}function a(a){d.lastIndex=0;return d.test(a)?'"'+a.replace(d,function(a){var b=i[a];return"string"===typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+ +'"':'"'+a+'"'}function f(b,c){var e,d,i,k,n=g,m,j=c[b];j&&"object"===typeof j&&"function"===typeof j.toJSON&&(j=j.toJSON(b));"function"===typeof l&&(j=l.call(c,b,j));switch(typeof j){case "string":return a(j);case "number":return isFinite(j)?""+j:"null";case "boolean":case "null":return""+j;case "object":if(!j)return"null";g+=h;m=[];if("[object Array]"===Object.prototype.toString.apply(j)){k=j.length;for(e=0;e\s*\(/gm,"{anonymous}()@").split("\n")},firefox:function(a){return a.stack.replace(/(?:\n@:0)?\s+$/m,"").replace(/^\(/gm,"{anonymous}(").split("\n")}, +opera10:function(a){var a=a.stacktrace.split("\n"),b=/.*line (\d+), column (\d+) in ((/g,"{anonymous}");a[d++]=i+"@"+h}a.splice(d,a.length-d);return a},opera:function(a){var a=a.message.split("\n"),b=/Line\s+(\d+).*script\s+(http\S+)(?:.*in\s+function\s+(\S+))?/i,c,d,g;c=4; +d=0;for(g=a.length;cc.length;){g=b.test(a.toString());h=[];try{h=Array.prototype.slice.call(a.arguments),a=a.caller}catch(i){a=null}g=g?RegExp.$1||"{anonymous}":"{anonymous}";c[d++]=g+"("+this.stringifyArguments(h)+")";if(!a)break}return c}, +stringifyArguments:function(a){for(var b=0;bc.length?"["+this.stringifyArguments(c)+"]":"["+this.stringifyArguments(Array.prototype.slice.call(c,0,1))+"..."+this.stringifyArguments(Array.prototype.slice.call(c,-1))+"]":c.constructor===Object?a[b]="#object":c.constructor===Function?a[b]="#function":c.constructor===String&&(a[b]='"'+c+'"'))}return a.join(",")}};c.stackTrace=b})(); +var t=k._eqatec||{};k._eqatec=t;t.createMonitor=function(b){var a=0,f="",e=!1,d={logError:function(){},logMessage:function(){}},g=0,h=!1,i=!1,l=0,t="",r="",w="",s={},x=!1,u=!0,n=!1,m=void 0,j=!1,y="",o={};try{b=b||{},f=c.trim(c.asString(b.productId))||"",d=b.loggingInterface||d,w=b.version,s=b.location||{},x=c.cookiesEnabled()&&b.useCookies,u=b.useHttps,m=b.userAgent,n=b.testMode,j=c.trackingDisabled(),y=c.getServerUri(d,f,b.serverUri,u),o=z(d),(32>f.length||36r.length||36 any; constructor(trackingId: string, baseInfo: AnalyticsBaseInfo) { - this._visitor = ua(trackingId); + this._visitor = ua(trackingId, baseInfo.userId, { requestOptions: {}, strictCidFormat: false }); this._getBasePayload = () => { return { uid: baseInfo.userId, - dh: baseInfo.hostname, + dh: 'ns-vs-extension.org', cd5: baseInfo.cliVersion, cd6: OperatingSystem[baseInfo.operatingSystem], cd7: baseInfo.extensionVersion diff --git a/src/services/analytics/TelerikAnalyticsService.ts b/src/services/analytics/TelerikAnalyticsService.ts new file mode 100644 index 0000000..b6caae6 --- /dev/null +++ b/src/services/analytics/TelerikAnalyticsService.ts @@ -0,0 +1,70 @@ +import { AnalyticsBaseInfo, OperatingSystem } from './AnalyticsBaseInfo'; +import * as os from 'os'; + +/** + * Google Universal Analytics Service + */ + +// Hack needed for the Telerik Analytics JavaScript monitor to work in node environment +(global as any).XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; +(global as any).XMLHttpRequest.prototype.withCredentials = false; + +function capitalizeFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +export class TelerikAnalyticsService { + + private _eqatecMonitor: any; + + private static getUserAgentString(): string { + let userAgentString: string; + let osType = os.type(); + if(osType === "Windows_NT") { + userAgentString = "(Windows NT " + os.release() + ")"; + } else if(osType === "Darwin") { + userAgentString = "(Mac OS X " + os.release() + ")"; + } else { + userAgentString = "(" + osType +")"; + } + + return userAgentString; + } + + constructor(projectKey: string, baseInfo: AnalyticsBaseInfo) { + require("./EqatecMonitor.min"); + let eqatec = (global as any)._eqatec; + let settings = eqatec.createSettings(projectKey); + settings.useHttps = false; + settings.userAgent = TelerikAnalyticsService.getUserAgentString(); + settings.version = baseInfo.extensionVersion; + settings.useCookies = false; + + /* + settings.loggingInterface = { + logMessage: console.log, + logError: console.log + }; + */ + + //settings.testMode = true; + this._eqatecMonitor = eqatec.createMonitor(settings); + this._eqatecMonitor.setInstallationID(baseInfo.userId); + this._eqatecMonitor.setUserID(baseInfo.userId); + this._eqatecMonitor.start(); + process.on('exit', () => { + this._eqatecMonitor.stop(); + }); + this._eqatecMonitor.trackFeature(`CLIVersion.${baseInfo.cliVersion}`); + } + + public launchDebugger(request: string, platform: string, emulator: boolean): Promise { + this._eqatecMonitor.trackFeature(`${capitalizeFirstLetter(request)}.${capitalizeFirstLetter(platform)}.${emulator ? 'Emulator' : 'Device'}`); + return Promise.resolve(); + } + + public runRunCommand(platform: string, emulator: boolean): Promise { + this._eqatecMonitor.trackFeature(`Run.${capitalizeFirstLetter(platform)}.${emulator ? 'Emulator' : 'Device'}`); + return Promise.resolve(); + } +} \ No newline at end of file diff --git a/src/services/ipc/ExtensionServer.ts b/src/services/ipc/ExtensionServer.ts index faa7cf3..a5ff954 100644 --- a/src/services/ipc/ExtensionServer.ts +++ b/src/services/ipc/ExtensionServer.ts @@ -66,6 +66,4 @@ export class ExtensionServer { public runRunCommand(args: extProtocol.AnalyticsRunRunCommandArgs): Promise { return AnalyticsService.getInstance().runRunCommand(args.platform, args.emulator); } - - } \ No newline at end of file