mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-14 01:25:37 -05:00
Support AD in cluster connection dialog (#7367)
- Use token API to get auth token before using other endpoints. Note this needs server updates before it'll work as expected (will only checkin after verifying this) - Add auth option in controller UI and plumb through connection save, load, and uses of the controller API Because the swagger spec is split in 2 created new file for the 2nd swagger spec including token auth endpoints. These come from a running cluster and instructions were updated to reflect this. New UI Changes: - Added authentication type field with "Basic" and "Windows Authentication" as the options - Moved error notifications to the dialog instead of separate notification window. That's the recommended pattern - Username / password aren't required for Windows Authentication. I couldn't find a way to change required status in form container on switching from Windows => Basic Auth so have error show on clicking OK. - Controller URL should use ":" not "," for IP:Port
This commit is contained in:
@@ -103,7 +103,8 @@ const indentationFilter = [
|
||||
'!extensions/admin-tool-ext-win/ssmsmin/**',
|
||||
'!extensions/resource-deployment/notebooks/**',
|
||||
'!extensions/mssql/notebooks/**',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts'
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts'
|
||||
];
|
||||
|
||||
const copyrightFilter = [
|
||||
@@ -191,7 +192,8 @@ const tslintBaseFilter = [
|
||||
'!extensions/vscode-api-tests/testWorkspace2/**',
|
||||
'!extensions/**/*.test.ts',
|
||||
'!extensions/html-language-features/server/lib/jquery.d.ts',
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts' // {{SQL CARBON EDIT}}
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts', // {{SQL CARBON EDIT}},
|
||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/tokenApiGenerated.ts' // {{SQL CARBON EDIT}}
|
||||
];
|
||||
|
||||
const sqlFilter = ['src/sql/**']; // {{SQL CARBON EDIT}}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
How to update the Swagger-generated API to contact the controller
|
||||
|
||||
## BdcRouter API:
|
||||
1. You need to get the API specification. Long-term you should be able to get from the server,
|
||||
but for now go to the internal repository and find the checked in SwaggerClient.yaml there.
|
||||
|
||||
@@ -9,4 +10,16 @@ but for now go to the internal repository and find the checked in SwaggerClient.
|
||||
5. Copy this content to apiGenerated.ts
|
||||
- keep the copyright header and everything above the let defaultBasePath = xyz line,
|
||||
- Override the rest of the file
|
||||
6. Format the apiGenerated.ts file so it passes gulp hygiene
|
||||
6. Format the apiGenerated.ts file so it passes gulp hygiene
|
||||
|
||||
## TokenRouter and other APIs:
|
||||
1. Get the API spec. This is available from a cluster at the address https://<ip>:30080/docs/swagger.json, where <ip> is the controller IP address.
|
||||
2. Copy the content from there, and add convert from OpenApi 3.0 to Swagger 2.0 so we can use the Typescript-Node client generated by https://editor.swagger.io/.
|
||||
Various converter tools are online. Alternatively, we might be able to use a different generator that has this client type (e.g. npm package @openapitools/openapi-generator-cli) but some require Java install.
|
||||
3. Copy the converted Swagger 2.0 spec into https://editor.swagger.io/
|
||||
4. Choose Generate Client, and choose Typescript-Node as the client to generate
|
||||
5. This will download a zip file. Open it and copy contents of api.ts
|
||||
6. Copy this content to tokenApiGenerated.ts
|
||||
- keep the copyright header and everything above the let defaultBasePath = xyz line,
|
||||
- Override the rest of the file
|
||||
7. Format the tokenApiGenerated.ts file so it passes gulp hygiene
|
||||
|
||||
@@ -101,10 +101,12 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"kerberos": "^1.1.3",
|
||||
"request": "^2.88.0",
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/kerberos": "^1.1.0",
|
||||
"@types/mocha": "^5.2.5",
|
||||
"@types/node": "^8.0.24",
|
||||
"mocha": "^5.2.0",
|
||||
|
||||
35
extensions/big-data-cluster/src/bigDataCluster/auth.ts
Normal file
35
extensions/big-data-cluster/src/bigDataCluster/auth.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as kerberos from 'kerberos';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export async function authenticateKerberos(hostname: string): Promise<string> {
|
||||
const service = 'HTTP' + (process.platform === 'win32' ? '/' : '@') + hostname;
|
||||
const mechOID = kerberos.GSS_MECH_OID_KRB5;
|
||||
let client = await kerberos.initializeClient(service, { mechOID });
|
||||
let response = await client.step('');
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
export type HostAndIp = { host: string, port: string };
|
||||
|
||||
export function getHostAndPortFromEndpoint(endpoint: string): HostAndIp {
|
||||
let authority = vscode.Uri.parse(endpoint).authority;
|
||||
let hostAndPortRegex = /^(.*)([,:](\d+))/g;
|
||||
let match = hostAndPortRegex.exec(authority);
|
||||
if (match) {
|
||||
return {
|
||||
host: match[1],
|
||||
port: match[3]
|
||||
};
|
||||
}
|
||||
return {
|
||||
host: authority,
|
||||
port: undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,3 +70,5 @@ export namespace cssStyles {
|
||||
export const unselectedTabDiv = { 'border-bottom': '1px solid #ccc' };
|
||||
export const lastUpdatedText = { ...text, 'color': '#595959' };
|
||||
}
|
||||
|
||||
export type AuthType = 'integrated' | 'basic';
|
||||
|
||||
@@ -631,8 +631,6 @@ export class BdcRouterApi {
|
||||
|
||||
this.authentications.default.applyToRequest(localVarRequestOptions);
|
||||
|
||||
this.authentications.basicAuth.applyToRequest(localVarRequestOptions);
|
||||
|
||||
if (Object.keys(localVarFormParams).length) {
|
||||
if (localVarUseFormData) {
|
||||
(<any>localVarRequestOptions).formData = localVarFormParams;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,14 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as request from 'request';
|
||||
import { BdcRouterApi, Authentication, DefaultApi, EndpointModel, BdcStatusModel } from './apiGenerated';
|
||||
import { authenticateKerberos, getHostAndPortFromEndpoint } from '../auth';
|
||||
import { BdcRouterApi, Authentication, EndpointModel, BdcStatusModel } from './apiGenerated';
|
||||
import { TokenRouterApi } from './clusterApiGenerated2';
|
||||
import { AuthType } from '../constants';
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
class AuthConfiguration implements Authentication {
|
||||
public username: string = '';
|
||||
public password: string = '';
|
||||
class SslAuth implements Authentication {
|
||||
|
||||
constructor(private _ignoreSslVerification: boolean) {
|
||||
}
|
||||
@@ -23,65 +24,153 @@ class AuthConfiguration implements Authentication {
|
||||
}
|
||||
}
|
||||
|
||||
export class KerberosAuth extends SslAuth implements Authentication {
|
||||
|
||||
constructor(public kerberosToken: string, ignoreSslVerification: boolean) {
|
||||
super(ignoreSslVerification);
|
||||
}
|
||||
|
||||
applyToRequest(requestOptions: request.Options): void {
|
||||
super.applyToRequest(requestOptions);
|
||||
if (requestOptions && requestOptions.headers) {
|
||||
requestOptions.headers['Authorization'] = `Negotiate ${this.kerberosToken}`;
|
||||
}
|
||||
requestOptions.auth = undefined;
|
||||
}
|
||||
}
|
||||
export class BasicAuth extends SslAuth implements Authentication {
|
||||
constructor(public username: string, public password: string, ignoreSslVerification: boolean) {
|
||||
super(ignoreSslVerification);
|
||||
}
|
||||
|
||||
applyToRequest(requestOptions: request.Options): void {
|
||||
super.applyToRequest(requestOptions);
|
||||
requestOptions.auth = {
|
||||
username: this.username, password: this.password
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class OAuthWithSsl extends SslAuth implements Authentication {
|
||||
public accessToken: string = '';
|
||||
|
||||
applyToRequest(requestOptions: request.Options): void {
|
||||
super.applyToRequest(requestOptions);
|
||||
if (requestOptions && requestOptions.headers) {
|
||||
requestOptions.headers['Authorization'] = `Bearer ${this.accessToken}`;
|
||||
}
|
||||
requestOptions.auth = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
class BdcApiWrapper extends BdcRouterApi {
|
||||
constructor(basePathOrUsername: string, password?: string, basePath?: string, ignoreSslVerification?: boolean) {
|
||||
super(basePathOrUsername, password, basePath);
|
||||
this.authentications.default = new AuthConfiguration(!!ignoreSslVerification);
|
||||
this.password = password;
|
||||
this.username = basePathOrUsername;
|
||||
constructor(basePathOrUsername: string, password: string, basePath: string, auth: Authentication) {
|
||||
if (password) {
|
||||
super(basePathOrUsername, password, basePath);
|
||||
} else {
|
||||
super(basePath, undefined, undefined);
|
||||
}
|
||||
this.authentications.default = auth;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getEndPoints(
|
||||
url: string,
|
||||
username: string,
|
||||
password: string,
|
||||
ignoreSslVerification?: boolean
|
||||
): Promise<IEndPointsResponse> {
|
||||
export class ClusterController {
|
||||
|
||||
if (!url || !username || !password) {
|
||||
return undefined;
|
||||
private authPromise: Promise<Authentication>;
|
||||
private _url: string;
|
||||
|
||||
constructor(url: string,
|
||||
private authType: AuthType,
|
||||
private username?: string,
|
||||
private password?: string,
|
||||
ignoreSslVerification?: boolean
|
||||
) {
|
||||
if (!url || (authType === 'basic' && (!username || !password))) {
|
||||
throw new Error('Missing required inputs for Cluster controller API (URL, username, password)');
|
||||
}
|
||||
this._url = adjustUrl(url);
|
||||
if (this.authType === 'basic') {
|
||||
this.authPromise = Promise.resolve(new BasicAuth(username, password, !!ignoreSslVerification));
|
||||
} else {
|
||||
this.authPromise = this.requestTokenUsingKerberos(ignoreSslVerification);
|
||||
}
|
||||
}
|
||||
|
||||
url = adjustUrl(url);
|
||||
let endPointApi = new BdcApiWrapper(username, password, url, !!ignoreSslVerification);
|
||||
private async requestTokenUsingKerberos(ignoreSslVerification?: boolean): Promise<Authentication> {
|
||||
let supportsKerberos = await this.verifyKerberosSupported(ignoreSslVerification);
|
||||
if (!supportsKerberos) {
|
||||
throw new Error(localize('error.no.activedirectory', "This cluster does not support Windows authentication"));
|
||||
}
|
||||
|
||||
try {
|
||||
let result = await endPointApi.endpointsGet();
|
||||
return {
|
||||
response: result.response as IHttpResponse,
|
||||
endPoints: result.body as EndpointModel[]
|
||||
};
|
||||
} catch (error) {
|
||||
throw new ControllerError(error, localize('bdc.error.getEndPoints', "Error retrieving endpoints from {0}", url));
|
||||
try {
|
||||
|
||||
// AD auth is available, login to keberos and convert to token auth for all future calls
|
||||
let host = getHostAndPortFromEndpoint(this._url).host;
|
||||
let kerberosToken = await authenticateKerberos(host);
|
||||
let tokenApi = new TokenRouterApi(this._url);
|
||||
tokenApi.setDefaultAuthentication(new KerberosAuth(kerberosToken, !!ignoreSslVerification));
|
||||
let result = await tokenApi.apiV1TokenPost();
|
||||
let auth = new OAuthWithSsl(ignoreSslVerification);
|
||||
auth.accessToken = result.body.accessToken;
|
||||
return auth;
|
||||
} catch (error) {
|
||||
let controllerErr = new ControllerError(error, localize('bdc.error.tokenPost', "Error during authentication"));
|
||||
if (controllerErr.code === 401) {
|
||||
throw new Error(localize('bdc.error.unauthorized', "You do not have permission to log into this cluster using Windows Authentication"));
|
||||
}
|
||||
// Else throw the error as-is
|
||||
throw controllerErr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async verifyKerberosSupported(ignoreSslVerification: boolean): Promise<boolean> {
|
||||
let tokenApi = new TokenRouterApi(this._url);
|
||||
tokenApi.setDefaultAuthentication(new SslAuth(!!ignoreSslVerification));
|
||||
try {
|
||||
await tokenApi.apiV1TokenPost();
|
||||
// If we get to here, the route for endpoints doesn't require auth so state this is false
|
||||
return false;
|
||||
}
|
||||
catch (error) {
|
||||
let auths = error && error.response && error.response.statusCode === 401 && error.response.headers['www-authenticate'];
|
||||
return auths && auths.includes('Negotiate');
|
||||
}
|
||||
}
|
||||
|
||||
public async getEndPoints(): Promise<IEndPointsResponse> {
|
||||
let auth = await this.authPromise;
|
||||
let endPointApi = new BdcApiWrapper(this.username, this.password, this._url, auth);
|
||||
let options: any = {};
|
||||
try {
|
||||
let result = await endPointApi.endpointsGet(options);
|
||||
return {
|
||||
response: result.response as IHttpResponse,
|
||||
endPoints: result.body as EndpointModel[]
|
||||
};
|
||||
} catch (error) {
|
||||
// TODO handle 401 by reauthenticating
|
||||
throw new ControllerError(error, localize('bdc.error.getEndPoints', "Error retrieving endpoints from {0}", this._url));
|
||||
}
|
||||
}
|
||||
|
||||
public async getBdcStatus(): Promise<IBdcStatusResponse> {
|
||||
let auth = await this.authPromise;
|
||||
const bdcApi = new BdcApiWrapper(this.username, this.password, this._url, auth);
|
||||
|
||||
try {
|
||||
const bdcStatus = await bdcApi.getBdcStatus('', '', /*all*/ true);
|
||||
return {
|
||||
response: bdcStatus.response,
|
||||
bdcStatus: bdcStatus.body
|
||||
};
|
||||
} catch (error) {
|
||||
// TODO handle 401 by reauthenticating
|
||||
throw new ControllerError(error, localize('bdc.error.getBdcStatus', "Error retrieving BDC status from {0}", this._url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getBdcStatus(
|
||||
url: string,
|
||||
username: string,
|
||||
password: string,
|
||||
ignoreSslVerification?: boolean
|
||||
): Promise<IBdcStatusResponse> {
|
||||
|
||||
if (!url) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
url = adjustUrl(url);
|
||||
const bdcApi = new BdcApiWrapper(username, password, url, ignoreSslVerification);
|
||||
|
||||
try {
|
||||
const bdcStatus = await bdcApi.getBdcStatus('', '', /*all*/ true);
|
||||
return {
|
||||
response: bdcStatus.response,
|
||||
bdcStatus: bdcStatus.body
|
||||
};
|
||||
} catch (error) {
|
||||
throw new ControllerError(error, localize('bdc.error.getBdcStatus', "Error retrieving BDC status from {0}", url));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes missing protocol and wrong character for port entered by user
|
||||
*/
|
||||
@@ -122,8 +211,7 @@ export interface IHttpResponse {
|
||||
}
|
||||
|
||||
export class ControllerError extends Error {
|
||||
public code?: string;
|
||||
public errno?: string;
|
||||
public code?: number;
|
||||
public reason?: string;
|
||||
public address?: string;
|
||||
|
||||
@@ -136,7 +224,7 @@ export class ControllerError extends Error {
|
||||
super(messagePrefix);
|
||||
// Pull out the response information containing details about the failure
|
||||
if (error.response) {
|
||||
this.code = error.response.statusCode || '';
|
||||
this.code = error.response.statusCode;
|
||||
this.message += `${error.response.statusMessage ? ` - ${error.response.statusMessage}` : ''}` || '';
|
||||
this.address = error.response.url || '';
|
||||
}
|
||||
|
||||
@@ -7,40 +7,74 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { getEndPoints, ControllerError } from '../controller/clusterControllerApi';
|
||||
import { ClusterController, ControllerError } from '../controller/clusterControllerApi';
|
||||
import { ControllerTreeDataProvider } from '../tree/controllerTreeDataProvider';
|
||||
import { TreeNode } from '../tree/treeNode';
|
||||
import { showErrorMessage } from '../utils';
|
||||
import { AuthType } from '../constants';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const basicAuthDisplay = localize('basicAuthName', "Basic");
|
||||
const integratedAuthDisplay = localize('integratedAuthName', "Windows Authentication");
|
||||
|
||||
function getAuthCategory(name: AuthType): azdata.CategoryValue {
|
||||
if (name === 'basic') {
|
||||
return { name: name, displayName: basicAuthDisplay };
|
||||
}
|
||||
return { name: name, displayName: integratedAuthDisplay };
|
||||
}
|
||||
|
||||
export class AddControllerDialogModel {
|
||||
|
||||
private _canceled = false;
|
||||
|
||||
private _authTypes: azdata.CategoryValue[];
|
||||
constructor(
|
||||
public treeDataProvider: ControllerTreeDataProvider,
|
||||
public node?: TreeNode,
|
||||
public prefilledUrl?: string,
|
||||
public prefilledAuth?: azdata.CategoryValue,
|
||||
public prefilledUsername?: string,
|
||||
public prefilledPassword?: string,
|
||||
public prefilledRememberPassword?: boolean
|
||||
) {
|
||||
this.prefilledUrl = prefilledUrl || (node && node['url']);
|
||||
this.prefilledAuth = prefilledAuth;
|
||||
if (!prefilledAuth) {
|
||||
let auth = (node && node['auth']) || 'basic';
|
||||
this.prefilledAuth = getAuthCategory(auth);
|
||||
}
|
||||
this.prefilledUsername = prefilledUsername || (node && node['username']);
|
||||
this.prefilledPassword = prefilledPassword || (node && node['password']);
|
||||
this.prefilledRememberPassword = prefilledRememberPassword || (node && node['rememberPassword']);
|
||||
}
|
||||
|
||||
public async onComplete(url: string, username: string, password: string, rememberPassword: boolean): Promise<void> {
|
||||
public get authCategories(): azdata.CategoryValue[] {
|
||||
if (!this._authTypes) {
|
||||
this._authTypes = [getAuthCategory('basic'), getAuthCategory('integrated')];
|
||||
}
|
||||
return this._authTypes;
|
||||
}
|
||||
|
||||
public async onComplete(url: string, auth: AuthType, username: string, password: string, rememberPassword: boolean): Promise<void> {
|
||||
try {
|
||||
|
||||
if (auth === 'basic') {
|
||||
// Verify username and password as we can't make them required in the UI
|
||||
if (!username) {
|
||||
throw new Error(localize('err.controller.username.required', "Username is required"));
|
||||
} else if (!password) {
|
||||
throw new Error(localize('err.controller.password.required', "Password is required"));
|
||||
}
|
||||
}
|
||||
// We pre-fetch the endpoints here to verify that the information entered is correct (the user is able to connect)
|
||||
let response = await getEndPoints(url, username, password, true);
|
||||
let controller = new ClusterController(url, auth, username, password, true);
|
||||
let response = await controller.getEndPoints();
|
||||
if (response && response.endPoints) {
|
||||
if (this._canceled) {
|
||||
return;
|
||||
}
|
||||
this.treeDataProvider.addController(url, username, password, rememberPassword);
|
||||
this.treeDataProvider.addController(url, auth, username, password, rememberPassword);
|
||||
await this.treeDataProvider.saveControllers();
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -70,6 +104,7 @@ export class AddControllerDialog {
|
||||
private uiModelBuilder: azdata.ModelBuilder;
|
||||
|
||||
private urlInputBox: azdata.InputBoxComponent;
|
||||
private authDropdown: azdata.DropDownComponent;
|
||||
private usernameInputBox: azdata.InputBoxComponent;
|
||||
private passwordInputBox: azdata.InputBoxComponent;
|
||||
private rememberPwCheckBox: azdata.CheckBoxComponent;
|
||||
@@ -92,6 +127,12 @@ export class AddControllerDialog {
|
||||
placeHolder: localize('textUrlLower', 'url'),
|
||||
value: this.model.prefilledUrl
|
||||
}).component();
|
||||
this.authDropdown = this.uiModelBuilder.dropDown().withProperties({
|
||||
values: this.model.authCategories,
|
||||
value: this.model.prefilledAuth,
|
||||
editable: false,
|
||||
}).component();
|
||||
this.authDropdown.onValueChanged(e => this.onAuthChanged());
|
||||
this.usernameInputBox = this.uiModelBuilder.inputBox()
|
||||
.withProperties<azdata.InputBoxProperties>({
|
||||
placeHolder: localize('textUsernameLower', 'username'),
|
||||
@@ -117,14 +158,18 @@ export class AddControllerDialog {
|
||||
component: this.urlInputBox,
|
||||
title: localize('textUrlCapital', 'URL'),
|
||||
required: true
|
||||
}, {
|
||||
component: this.authDropdown,
|
||||
title: localize('textAuthCapital', 'Authentication type'),
|
||||
required: true
|
||||
}, {
|
||||
component: this.usernameInputBox,
|
||||
title: localize('textUsernameCapital', 'Username'),
|
||||
required: true
|
||||
required: false
|
||||
}, {
|
||||
component: this.passwordInputBox,
|
||||
title: localize('textPasswordCapital', 'Password'),
|
||||
required: true
|
||||
required: false
|
||||
}, {
|
||||
component: this.rememberPwCheckBox,
|
||||
title: ''
|
||||
@@ -142,17 +187,36 @@ export class AddControllerDialog {
|
||||
this.dialog.cancelButton.label = localize('textCancel', 'Cancel');
|
||||
}
|
||||
|
||||
private get authValue(): AuthType {
|
||||
return (<azdata.CategoryValue>this.authDropdown.value).name as AuthType;
|
||||
}
|
||||
|
||||
private onAuthChanged(): void {
|
||||
let isBasic = this.authValue === 'basic';
|
||||
this.usernameInputBox.enabled = isBasic;
|
||||
this.passwordInputBox.enabled = isBasic;
|
||||
this.rememberPwCheckBox.enabled = isBasic;
|
||||
if (!isBasic) {
|
||||
this.usernameInputBox.value = '';
|
||||
this.passwordInputBox.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
private async validate(): Promise<boolean> {
|
||||
let url = this.urlInputBox && this.urlInputBox.value;
|
||||
let auth = this.authValue;
|
||||
let username = this.usernameInputBox && this.usernameInputBox.value;
|
||||
let password = this.passwordInputBox && this.passwordInputBox.value;
|
||||
let rememberPassword = this.passwordInputBox && !!this.rememberPwCheckBox.checked;
|
||||
|
||||
try {
|
||||
await this.model.onComplete(url, username, password, rememberPassword);
|
||||
await this.model.onComplete(url, auth, username, password, rememberPassword);
|
||||
return true;
|
||||
} catch (error) {
|
||||
showErrorMessage(error);
|
||||
this.dialog.message = {
|
||||
text: (typeof error === 'string') ? error : error.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
if (this.model && this.model.onError) {
|
||||
await this.model.onError(error as ControllerError);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { getBdcStatus, getEndPoints } from '../controller/clusterControllerApi';
|
||||
import { ClusterController } from '../controller/clusterControllerApi';
|
||||
import { EndpointModel, BdcStatusModel } from '../controller/apiGenerated';
|
||||
import { showErrorMessage, Endpoint } from '../utils';
|
||||
import { AuthType } from '../constants';
|
||||
|
||||
export class BdcDashboardModel {
|
||||
|
||||
private _clusterController: ClusterController;
|
||||
private _bdcStatus: BdcStatusModel;
|
||||
private _endpoints: EndpointModel[] = [];
|
||||
private _bdcStatusLastUpdated: Date;
|
||||
@@ -22,7 +24,8 @@ export class BdcDashboardModel {
|
||||
public onDidUpdateEndpoints = this._onDidUpdateEndpoints.event;
|
||||
public onDidUpdateBdcStatus = this._onDidUpdateBdcStatus.event;
|
||||
|
||||
constructor(private url: string, private username: string, private password: string) {
|
||||
constructor(url: string, auth: AuthType, username: string, private password: string, ignoreSslVerification = true) {
|
||||
this._clusterController = new ClusterController(url, auth, username, password, ignoreSslVerification);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
@@ -44,18 +47,20 @@ export class BdcDashboardModel {
|
||||
|
||||
public async refresh(): Promise<void> {
|
||||
await Promise.all([
|
||||
getBdcStatus(this.url, this.username, this.password, true).then(response => {
|
||||
this._clusterController.getBdcStatus().then(response => {
|
||||
this._bdcStatus = response.bdcStatus;
|
||||
this._bdcStatusLastUpdated = new Date();
|
||||
this._onDidUpdateBdcStatus.fire(this.bdcStatus);
|
||||
}),
|
||||
getEndPoints(this.url, this.username, this.password, true).then(response => {
|
||||
this._clusterController.getEndPoints().then(response => {
|
||||
this._endpoints = response.endPoints || [];
|
||||
fixEndpoints(this._endpoints);
|
||||
this._endpointsLastUpdated = new Date();
|
||||
this._onDidUpdateEndpoints.fire(this.serviceEndpoints);
|
||||
})
|
||||
]).catch(error => showErrorMessage(error));
|
||||
]).catch(error => {
|
||||
showErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,11 +13,13 @@ import { AddControllerNode } from './addControllerNode';
|
||||
import { ControllerRootNode, ControllerNode } from './controllerTreeNode';
|
||||
import { showErrorMessage } from '../utils';
|
||||
import { LoadingControllerNode } from './loadingControllerNode';
|
||||
import { AuthType } from '../constants';
|
||||
|
||||
const CredentialNamespace = 'clusterControllerCredentials';
|
||||
|
||||
interface IControllerInfoSlim {
|
||||
url: string;
|
||||
auth: AuthType;
|
||||
username: string;
|
||||
password?: string;
|
||||
rememberPassword: boolean;
|
||||
@@ -57,17 +59,18 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
|
||||
|
||||
public addController(
|
||||
url: string,
|
||||
auth: AuthType,
|
||||
username: string,
|
||||
password: string,
|
||||
rememberPassword: boolean
|
||||
): void {
|
||||
this.removeNonControllerNodes();
|
||||
this.root.addControllerNode(url, username, password, rememberPassword);
|
||||
this.root.addControllerNode(url, auth, username, password, rememberPassword);
|
||||
this.notifyNodeChanged();
|
||||
}
|
||||
|
||||
public deleteController(url: string, username: string): ControllerNode {
|
||||
let deleted = this.root.deleteControllerNode(url, username);
|
||||
public deleteController(url: string, auth: AuthType, username: string): ControllerNode {
|
||||
let deleted = this.root.deleteControllerNode(url, auth, username);
|
||||
if (deleted) {
|
||||
this.notifyNodeChanged();
|
||||
}
|
||||
@@ -115,8 +118,12 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
|
||||
if (c.rememberPassword) {
|
||||
password = await this.getPassword(c.url, c.username);
|
||||
}
|
||||
if (!c.auth) {
|
||||
// Added before we had added authentication
|
||||
c.auth = 'basic';
|
||||
}
|
||||
this.root.addChild(new ControllerNode(
|
||||
c.url, c.username, password, c.rememberPassword,
|
||||
c.url, c.auth, c.username, password, c.rememberPassword,
|
||||
undefined, this.root, this, undefined
|
||||
));
|
||||
}
|
||||
@@ -135,6 +142,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
|
||||
let controller = e as ControllerNode;
|
||||
return {
|
||||
url: controller.url,
|
||||
auth: controller.auth,
|
||||
username: controller.username,
|
||||
password: controller.password,
|
||||
rememberPassword: !!controller.rememberPassword
|
||||
@@ -144,6 +152,7 @@ export class ControllerTreeDataProvider implements vscode.TreeDataProvider<TreeN
|
||||
let controllersWithoutPassword = controllers.map((e): IControllerInfoSlim => {
|
||||
return {
|
||||
url: e.url,
|
||||
auth: e.auth,
|
||||
username: e.username,
|
||||
rememberPassword: e.rememberPassword
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as azdata from 'azdata';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { IControllerTreeChangeHandler } from './controllerTreeChangeHandler';
|
||||
import { TreeNode } from './treeNode';
|
||||
import { IconPathHelper, BdcItemType, IconPath } from '../constants';
|
||||
import { IconPathHelper, BdcItemType, IconPath, AuthType } from '../constants';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -108,27 +108,28 @@ export class ControllerRootNode extends ControllerTreeNode {
|
||||
|
||||
public addControllerNode(
|
||||
url: string,
|
||||
auth: AuthType,
|
||||
username: string,
|
||||
password: string,
|
||||
rememberPassword: boolean
|
||||
): void {
|
||||
let controllerNode = this.getExistingControllerNode(url, username);
|
||||
let controllerNode = this.getExistingControllerNode(url, auth, username);
|
||||
if (controllerNode) {
|
||||
controllerNode.password = password;
|
||||
controllerNode.rememberPassword = rememberPassword;
|
||||
controllerNode.clearChildren();
|
||||
} else {
|
||||
controllerNode = new ControllerNode(url, username, password, rememberPassword, undefined, this, this.treeChangeHandler, undefined);
|
||||
controllerNode = new ControllerNode(url, auth, username, password, rememberPassword, undefined, this, this.treeChangeHandler, undefined);
|
||||
this.addChild(controllerNode);
|
||||
}
|
||||
}
|
||||
|
||||
public deleteControllerNode(url: string, username: string): ControllerNode {
|
||||
if (!url || !username) {
|
||||
public deleteControllerNode(url: string, auth: AuthType, username: string): ControllerNode {
|
||||
if (!url || (auth === 'basic' && !username)) {
|
||||
return undefined;
|
||||
}
|
||||
let nodes = this.children as ControllerNode[];
|
||||
let index = nodes.findIndex(e => e.url === url && e.username === username);
|
||||
let index = nodes.findIndex(e => isControllerMatch(e, url, auth, username));
|
||||
let deleted = undefined;
|
||||
if (index >= 0) {
|
||||
deleted = nodes.splice(index, 1);
|
||||
@@ -136,12 +137,12 @@ export class ControllerRootNode extends ControllerTreeNode {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
private getExistingControllerNode(url: string, username: string): ControllerNode {
|
||||
private getExistingControllerNode(url: string, auth: AuthType, username: string): ControllerNode {
|
||||
if (!url || !username) {
|
||||
return undefined;
|
||||
}
|
||||
let nodes = this.children as ControllerNode[];
|
||||
return nodes.find(e => e.url === url && e.username === username);
|
||||
return nodes.find(e => isControllerMatch(e, url, auth, username));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +150,7 @@ export class ControllerNode extends ControllerTreeNode {
|
||||
|
||||
constructor(
|
||||
private _url: string,
|
||||
private _auth: AuthType,
|
||||
private _username: string,
|
||||
private _password: string,
|
||||
private _rememberPassword: boolean,
|
||||
@@ -177,26 +179,24 @@ export class ControllerNode extends ControllerTreeNode {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
return url.trim().replace(/ /g, '').replace(/^.+\:\/\//, '').replace(/:(\d+)$/, ',$1');
|
||||
return url.trim().replace(/ /g, '').replace(/^.+\:\/\//, '');
|
||||
}
|
||||
|
||||
public get url() {
|
||||
public get url(): string {
|
||||
return this._url;
|
||||
}
|
||||
|
||||
public set url(url: string) {
|
||||
this._url = url;
|
||||
|
||||
public get auth(): AuthType {
|
||||
return this._auth;
|
||||
}
|
||||
|
||||
public get username() {
|
||||
|
||||
public get username(): string {
|
||||
return this._username;
|
||||
}
|
||||
|
||||
public set username(username: string) {
|
||||
this._username = username;
|
||||
}
|
||||
|
||||
public get password() {
|
||||
public get password(): string {
|
||||
return this._password;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,15 @@ export class ControllerNode extends ControllerTreeNode {
|
||||
}
|
||||
|
||||
public set label(label: string) {
|
||||
super.label = label || `controller: ${ControllerNode.toIpAndPort(this._url)} (${this._username})`;
|
||||
super.label = label || this.generateLabel();
|
||||
}
|
||||
|
||||
private generateLabel(): string {
|
||||
let label = `controller: ${ControllerNode.toIpAndPort(this._url)}`;
|
||||
if (this._auth === 'basic') {
|
||||
label += ` (${this._username})`;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
public get label(): string {
|
||||
@@ -229,3 +237,7 @@ export class ControllerNode extends ControllerTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
function isControllerMatch(node: ControllerNode, url: string, auth: string, username: string): unknown {
|
||||
return node.url === url && node.auth === auth && node.username === username;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,9 +59,10 @@ export function showErrorMessage(error: any, prefixText?: string): void {
|
||||
if (typeof error === 'string') {
|
||||
text += error as string;
|
||||
} else if (typeof error === 'object' && error !== null) {
|
||||
let message = error.message;
|
||||
let code = error.code || error.errno;
|
||||
text += `${message}${code ? ` (${code})` : ''}`;
|
||||
text += error.message;
|
||||
if (error.code && error.code > 0) {
|
||||
text += ` (${error.code})`;
|
||||
}
|
||||
} else {
|
||||
text += `${error}`;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ function registerCommands(context: vscode.ExtensionContext, treeDataProvider: Co
|
||||
|
||||
vscode.commands.registerCommand(ManageControllerCommand, async (node: ControllerNode) => {
|
||||
const title: string = `${localize('bdc.dashboard.title', "Big Data Cluster Dashboard -")} ${ControllerNode.toIpAndPort(node.url)}`;
|
||||
const dashboard: BdcDashboard = new BdcDashboard(title, new BdcDashboardModel(node.url, node.username, node.password));
|
||||
const dashboard: BdcDashboard = new BdcDashboard(title, new BdcDashboardModel(node.url, node.auth, node.username, node.password));
|
||||
dashboard.showDashboard();
|
||||
});
|
||||
}
|
||||
@@ -92,7 +92,7 @@ async function deleteBdcController(treeDataProvider: ControllerTreeDataProvider,
|
||||
}
|
||||
|
||||
function deleteControllerInternal(treeDataProvider: ControllerTreeDataProvider, controllerNode: ControllerNode): void {
|
||||
let deleted = treeDataProvider.deleteController(controllerNode.url, controllerNode.username);
|
||||
let deleted = treeDataProvider.deleteController(controllerNode.url, controllerNode.auth, controllerNode.username);
|
||||
if (deleted) {
|
||||
treeDataProvider.saveControllers();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/kerberos@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/kerberos/-/kerberos-1.1.0.tgz#fb1e5bc4f7272d152f67714deb100d5de7cb3e48"
|
||||
integrity sha512-ixpV6PSSMnIVpMNCLQ0gWguC2+pBxc0LeUCv9Ugj54opVSVFXfPNYP6sMa7UHvicYGDXAyHQSAzQC8VYEIgdFQ==
|
||||
|
||||
"@types/mocha@^5.2.5":
|
||||
version "5.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea"
|
||||
@@ -29,6 +34,29 @@ ajv@^6.5.5:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
|
||||
|
||||
ansi-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||
|
||||
aproba@^1.0.3:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
||||
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
||||
|
||||
are-we-there-yet@~1.1.2:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
|
||||
integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
asn1@~0.2.3:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||
@@ -68,6 +96,20 @@ bcrypt-pbkdf@^1.0.0:
|
||||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
bindings@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
|
||||
dependencies:
|
||||
file-uri-to-path "1.0.0"
|
||||
|
||||
bl@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
|
||||
integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==
|
||||
dependencies:
|
||||
readable-stream "^3.0.1"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@@ -91,11 +133,21 @@ caseless@~0.12.0:
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||
|
||||
chownr@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6"
|
||||
integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==
|
||||
|
||||
circular-json@^0.3.1:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
|
||||
integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==
|
||||
|
||||
code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
@@ -113,7 +165,12 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
core-util-is@1.0.2:
|
||||
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
@@ -139,11 +196,33 @@ debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
decompress-response@^4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
|
||||
integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
|
||||
dependencies:
|
||||
mimic-response "^2.0.0"
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
@@ -157,6 +236,13 @@ ecc-jsbn@~0.1.1:
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
|
||||
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
es6-promise@^4.0.3:
|
||||
version "4.2.8"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||
@@ -174,6 +260,11 @@ escape-string-regexp@1.0.5:
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
expand-template@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||
|
||||
extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
@@ -199,6 +290,11 @@ fast-json-stable-stringify@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
@@ -213,11 +309,30 @@ form-data@~2.3.2:
|
||||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs-constants@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
gauge@~2.7.3:
|
||||
version "2.7.4"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||
integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
|
||||
dependencies:
|
||||
aproba "^1.0.3"
|
||||
console-control-strings "^1.0.0"
|
||||
has-unicode "^2.0.0"
|
||||
object-assign "^4.1.0"
|
||||
signal-exit "^3.0.0"
|
||||
string-width "^1.0.1"
|
||||
strip-ansi "^3.0.1"
|
||||
wide-align "^1.1.0"
|
||||
|
||||
getpass@^0.1.1:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||
@@ -225,6 +340,11 @@ getpass@^0.1.1:
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
github-from-package@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
|
||||
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
@@ -272,6 +392,11 @@ has-flag@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
has-unicode@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
|
||||
|
||||
he@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
@@ -315,11 +440,38 @@ inherits@2:
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
inherits@^2.0.3, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ini@~1.3.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
|
||||
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
|
||||
|
||||
is-fullwidth-code-point@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
|
||||
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
|
||||
dependencies:
|
||||
number-is-nan "^1.0.0"
|
||||
|
||||
is-fullwidth-code-point@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isstream@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
@@ -355,6 +507,15 @@ jsprim@^1.2.2:
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
kerberos@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/kerberos/-/kerberos-1.1.3.tgz#74c5620d09289e4a53beddc2d9a93eccfebd964d"
|
||||
integrity sha512-R6LdXnkSTALLnrKaByYdIc+eRNhDf+ezA83BeqHiCcKhKE9R6m1PBD579YuX9KANPAakhWHEu/u6H7ZQBc/+Wg==
|
||||
dependencies:
|
||||
bindings "^1.5.0"
|
||||
nan "^2.14.0"
|
||||
prebuild-install "^5.3.0"
|
||||
|
||||
lodash@^4.17.4:
|
||||
version "4.17.11"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
|
||||
@@ -372,6 +533,11 @@ mime-types@^2.1.12, mime-types@~2.1.19:
|
||||
dependencies:
|
||||
mime-db "1.40.0"
|
||||
|
||||
mimic-response@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46"
|
||||
integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ==
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
@@ -384,7 +550,12 @@ minimist@0.0.8:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||
|
||||
mkdirp@0.5.1:
|
||||
minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||
|
||||
mkdirp@0.5.1, mkdirp@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
|
||||
@@ -418,12 +589,54 @@ ms@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
nan@^2.14.0:
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||
|
||||
napi-build-utils@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508"
|
||||
integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==
|
||||
|
||||
node-abi@^2.7.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.11.0.tgz#b7dce18815057544a049be5ae75cd1fdc2e9ea59"
|
||||
integrity sha512-kuy/aEg75u40v378WRllQ4ZexaXJiCvB68D2scDXclp/I4cRq6togpbOoKhmN07tns9Zldu51NNERo0wehfX9g==
|
||||
dependencies:
|
||||
semver "^5.4.1"
|
||||
|
||||
noop-logger@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
|
||||
integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
|
||||
|
||||
npmlog@^4.0.1:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
dependencies:
|
||||
are-we-there-yet "~1.1.2"
|
||||
console-control-strings "~1.1.0"
|
||||
gauge "~2.7.3"
|
||||
set-blocking "~2.0.0"
|
||||
|
||||
number-is-nan@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||
|
||||
oauth-sign@~0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
once@^1.3.0:
|
||||
object-assign@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||
@@ -445,11 +658,45 @@ postinstall-build@^5.0.1:
|
||||
resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7"
|
||||
integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg==
|
||||
|
||||
prebuild-install@^5.3.0:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.2.tgz#6392e9541ac0b879ef0f22b3d65037417eb2035e"
|
||||
integrity sha512-INDfXzTPnhT+WYQemqnAXlP7SvfiFMopMozSgXCZ+RDLb279gKfIuLk4o7PgEawLp3WrMgIYGBpkxpraROHsSA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
expand-template "^2.0.3"
|
||||
github-from-package "0.0.0"
|
||||
minimist "^1.2.0"
|
||||
mkdirp "^0.5.1"
|
||||
napi-build-utils "^1.0.1"
|
||||
node-abi "^2.7.0"
|
||||
noop-logger "^0.1.1"
|
||||
npmlog "^4.0.1"
|
||||
pump "^3.0.0"
|
||||
rc "^1.2.7"
|
||||
simple-get "^3.0.3"
|
||||
tar-fs "^2.0.0"
|
||||
tunnel-agent "^0.6.0"
|
||||
which-pm-runs "^1.0.0"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
psl@^1.1.24:
|
||||
version "1.1.32"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.32.tgz#3f132717cf2f9c169724b2b6caf373cf694198db"
|
||||
integrity sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
punycode@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
@@ -470,6 +717,38 @@ querystringify@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
||||
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
|
||||
|
||||
rc@^1.2.7:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
|
||||
dependencies:
|
||||
deep-extend "^0.6.0"
|
||||
ini "~1.3.0"
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
readable-stream@^2.0.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.0.1, readable-stream@^3.1.1:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
|
||||
integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
request@^2.88.0:
|
||||
version "2.88.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
||||
@@ -501,11 +780,16 @@ requires-port@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@~5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||
|
||||
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
@@ -516,6 +800,11 @@ semver@^5.4.1:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
|
||||
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
|
||||
|
||||
set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||
|
||||
should-equal@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3"
|
||||
@@ -560,6 +849,25 @@ should@^13.2.1:
|
||||
should-type-adaptors "^1.0.1"
|
||||
should-util "^1.0.0"
|
||||
|
||||
signal-exit@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
|
||||
|
||||
simple-concat@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
|
||||
integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=
|
||||
|
||||
simple-get@^3.0.3:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
|
||||
integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
|
||||
dependencies:
|
||||
decompress-response "^4.2.0"
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
source-map-support@^0.5.0:
|
||||
version "0.5.12"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
|
||||
@@ -588,6 +896,56 @@ sshpk@^1.7.0:
|
||||
safer-buffer "^2.0.2"
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
string-width@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
||||
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
|
||||
dependencies:
|
||||
code-point-at "^1.0.0"
|
||||
is-fullwidth-code-point "^1.0.0"
|
||||
strip-ansi "^3.0.0"
|
||||
|
||||
"string-width@^1.0.2 || 2":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
|
||||
dependencies:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string_decoder@^1.1.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
strip-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||
integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
|
||||
dependencies:
|
||||
ansi-regex "^3.0.0"
|
||||
|
||||
strip-json-comments@~2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||
|
||||
supports-color@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||
@@ -595,6 +953,27 @@ supports-color@5.4.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
tar-fs@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad"
|
||||
integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
mkdirp "^0.5.1"
|
||||
pump "^3.0.0"
|
||||
tar-stream "^2.0.0"
|
||||
|
||||
tar-stream@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
|
||||
integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==
|
||||
dependencies:
|
||||
bl "^3.0.0"
|
||||
end-of-stream "^1.4.1"
|
||||
fs-constants "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tough-cookie@~2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
@@ -639,6 +1018,11 @@ url-parse@^1.4.4:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
@@ -679,6 +1063,18 @@ vscode@^1.1.26:
|
||||
url-parse "^1.4.4"
|
||||
vscode-test "^0.4.1"
|
||||
|
||||
which-pm-runs@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
|
||||
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
|
||||
|
||||
wide-align@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||
integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
|
||||
dependencies:
|
||||
string-width "^1.0.2 || 2"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
|
||||
Reference in New Issue
Block a user