diff --git a/.gitignore b/.gitignore index 160c42ed74..5ade800848 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ coverage/ test_data/ test-results/ yarn-error.log +*.vsix diff --git a/extensions/liveshare/.vscodeignore b/extensions/liveshare/.vscodeignore new file mode 100644 index 0000000000..acc1856e97 --- /dev/null +++ b/extensions/liveshare/.vscodeignore @@ -0,0 +1,5 @@ +src/** +out/** +tsconfig.json +extension.webpack.config.js +yarn.lock diff --git a/extensions/liveshare/package.json b/extensions/liveshare/package.json new file mode 100644 index 0000000000..644ddd1c37 --- /dev/null +++ b/extensions/liveshare/package.json @@ -0,0 +1,30 @@ +{ + "name": "liveshare", + "version": "0.1.0", + "publisher": "Microsoft", + "aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412", + "activationEvents": [ + "*" + ], + "engines": { + "vscode": "*" + }, + "main": "./out/main", + "extensionDependencies": [ + "vscode.sql" + ], + "scripts": { + "compile": "gulp compile-extension:liveshare" + }, + "devDependencies": { + "@types/node": "12.0.9", + "ts-loader": "^5.3.3", + "tslint": "^5.12.1", + "typescript": "^3.3.1", + "vscode": "^1.1.33" + }, + "dependencies": { + "dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.3.0", + "vsls": "^0.3.1291" + } +} diff --git a/extensions/liveshare/src/constants.ts b/extensions/liveshare/src/constants.ts new file mode 100644 index 0000000000..0fd74e110b --- /dev/null +++ b/extensions/liveshare/src/constants.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Provider Constants + */ +export const LiveShareProviderId: string = 'ads-liveshare'; +export const LiveShareServiceName: string = 'ads-liveshare'; +export const VslsSchema: string = 'vsls'; + +/** + * Connection Provider Constants + */ +export const connectRequest = 'connect'; +export const disconnectRequest = 'disconnect'; +export const cancelConnectRequest = 'cancelConnect'; +export const changeDatabaseRequest = 'changeDatabase'; +export const listDatabasesRequest = 'listDatabases'; +export const getConnectionStringRequest = 'getConnectionString'; +export const buildConnectionInfoRequest = 'buildConnectionInfo'; +export const rebuildIntellisenseCacheRequest = 'rebuildIntelliSenseCache'; + +/** + * Query Provider Constants + */ +export const cancelQueryRequest = 'cancelQuery'; +export const runQueryRequest = 'runQuery'; +export const runQueryStatementRequest = 'runQueryStatement'; +export const runQueryStringRequest = 'runQueryString'; +export const runQueryAndReturnRequest = 'runQueryAndReturn'; +export const parseSyntaxRequest = 'parseSyntax'; +export const getQueryRowsRequest = 'getQueryRows'; +export const disposeQueryRequest = 'disposeQuery'; +export const setQueryExecutionOptionsRequest = 'setQueryExecutionOptions'; +export const saveResultsRequest = 'saveResultsRequest'; diff --git a/extensions/liveshare/src/guestSessionManager.ts b/extensions/liveshare/src/guestSessionManager.ts new file mode 100644 index 0000000000..8b1941d9a8 --- /dev/null +++ b/extensions/liveshare/src/guestSessionManager.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as azdata from 'azdata'; +import { LiveShare, SharedServiceProxy } from './liveshare'; +import { LiveShareProviderId, LiveShareServiceName, VslsSchema } from './constants'; +import { ConnectionProvider } from './providers/connectionProvider'; +import { StatusProvider, LiveShareDocumentState } from './providers/statusProvider'; +import { QueryProvider } from './providers/queryProvider'; + +declare var require: any; +let vsls = require('vsls'); + +export class GuestSessionManager { + private _statusProvider: StatusProvider; + + constructor( + context: vscode.ExtensionContext, + vslsApi: LiveShare + ) { + let self = this; + vscode.workspace.onDidOpenTextDocument(params => this.onDidOpenTextDocument(params)); + + vslsApi!.onDidChangeSession(async function onLiveShareSessionCHange(e: any) { + const isHost = e.session.role === vsls.Role.Host; + if (!e.session.id && isHost) { + return; + } + + const sharedServiceProxy: SharedServiceProxy = await vslsApi.getSharedService(LiveShareServiceName); + if (!sharedServiceProxy) { + vscode.window.showErrorMessage('Could not access a shared service. You have to set "liveshare.features" to "experimental" in your user settings in order to use this extension.'); + return; + } + + const connectionProvider = new ConnectionProvider(isHost, vslsApi, sharedServiceProxy); + + const queryProvider = new QueryProvider(false); + queryProvider.initialize(false, sharedServiceProxy); + + self._statusProvider = new StatusProvider( + isHost, + vslsApi, + connectionProvider, + sharedServiceProxy); + }); + } + + private async onDidOpenTextDocument(doc: vscode.TextDocument): Promise { + if (this._statusProvider && this.isLiveShareDocument(doc)) { + let documentState: LiveShareDocumentState = await this._statusProvider.getDocumentState(doc); + if (documentState) { + let queryDocument = await azdata.queryeditor.getQueryDocument(doc.uri.toString()); + if (queryDocument) { + let connectionOptions: Map = new Map(); + connectionOptions['providerName'] = LiveShareProviderId; + connectionOptions['serverName'] = documentState.serverName; + connectionOptions['databaseName'] = documentState.databaseName; + connectionOptions['userName'] = 'liveshare'; + connectionOptions['password'] = 'liveshare'; + connectionOptions['authenticationType'] = 'liveshare'; + connectionOptions['savePassword'] = false; + connectionOptions['saveProfile'] = false; + let profile = azdata.connection.ConnectionProfile.createFrom(connectionOptions); + queryDocument.connect(profile); + } + } + } + } + + private isLiveShareDocument(doc: vscode.TextDocument): boolean { + return doc && doc.uri.scheme === VslsSchema; + } +} diff --git a/extensions/liveshare/src/hostSessionManager.ts b/extensions/liveshare/src/hostSessionManager.ts new file mode 100644 index 0000000000..63c12a3676 --- /dev/null +++ b/extensions/liveshare/src/hostSessionManager.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { LiveShare, SharedService } from './liveshare'; +import { ConnectionProvider } from './providers/connectionProvider'; +import { QueryProvider } from './providers/queryProvider'; +import { StatusProvider } from './providers/statusProvider'; +import { LiveShareServiceName } from './constants'; + +declare var require: any; +let vsls = require('vsls'); + +export class HostSessionManager { + constructor( + context: vscode.ExtensionContext, + vslsApi: LiveShare + ) { + vslsApi!.onDidChangeSession(async function onLiveShareSessionCHange(e: any) { + const isHost = e.session.role === vsls.Role.Host; + if (!isHost) { + return; + } + + const sharedService: SharedService = await vslsApi.shareService(LiveShareServiceName); + if (!sharedService) { + vscode.window.showErrorMessage('Could not create a shared service. You have to set "liveshare.features" to "experimental" in your user settings in order to use this extension.'); + return; + } + + const connectionProvider = new ConnectionProvider(isHost, vslsApi, sharedService); + + const queryProvider = new QueryProvider(true); + queryProvider.initialize(true, sharedService); + + /* tslint:disable:no-unused-expression */ + new StatusProvider( + isHost, + vslsApi, + connectionProvider, + sharedService); + /* tslint:enable:no-unused-expression */ + }); + } +} diff --git a/extensions/liveshare/src/liveshare.ts b/extensions/liveshare/src/liveshare.ts new file mode 100644 index 0000000000..41012cfb0c --- /dev/null +++ b/extensions/liveshare/src/liveshare.ts @@ -0,0 +1,559 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Entrypoint and type definitions for Live Share for VS Code extension API + */ + +import * as vscode from 'vscode'; + +/** + * Root API that is used to acquire access to the main Live Share API. + * + * An implementation of this interface is returned by the Live Share extension's + * activation function. Ordinarily this interface is not used directly; use the + * `getApiAsync()` helper function above instead. + */ +export interface LiveShareExtension { + /** + * Requests a specific version of the Live Share API for use by another extension. + * + * @returns a promise that resolves to the requested API, or `null` if the requested + * API is not available + */ + getApi(requestedApiVersion: string): Promise; +} + +/** + * Forward definition of the ContactServiceProvider interface + */ +export interface ContactServiceProvider { + +} + +/** + * Main API that enables other VS Code extensions to access Live Share capabilities. + */ +export interface LiveShare { + /** + * Status of participation in a sharing session, if any. + * Also includes the Live Share user info, if signed in. + */ + readonly session: Session; + + /** + * Event that notifies listeners when participation in a sharing session + * starts or stops. + */ + readonly onDidChangeSession: vscode.Event; + + /** List of peers connected to the current sharing session, NOT including oneself. */ + readonly peers: Peer[]; + + /** Event that notifies listeners when peers join or leave the session. */ + readonly onDidChangePeers: vscode.Event; + + /** + * Starts a new session, sharing the currenly opened workspace. + * Or if sharing was already started, retrieves the join link. + * + * Not valid when joined to a session as a guest. + * + * @returns Join link for the new or existing session, or `null` if sharing failed. + */ + share(options?: ShareOptions): Promise; + + /** + * Joins a shared session using a link acquired from the host. + * + * Note joining another session requires either reloading the current window + * (and all extensions) or opening a new window. + * + * @param link Join link for a shared session. + */ + join(link: vscode.Uri, options?: JoinOptions): Promise; + + /** + * When called as a Host, ends the current sharing session and disconnects all guests, + * (without reloading the window or extensions). + * + * When called as a Guest, disconnects from the current sharing session + * and closes the workspace (causing extensions to be reloaded). + */ + end(): Promise; + + /** + * Provides a named service to guests. The service is made available only + * while a Live Share session is active in the Host role. + * + * The caller must add request and/or notification handlers to the returned + * `SharedService` instance in order to receive messages from guests. + * + * A `SharedService` instance is returned even if the service is not + * currently made available because there is no hosted sharing session. + * The service will be automatically made available when a hosted sharing + * session begins. + * + * NOTE: Access to shared services may be restricted. + * If the caller is not permitted, this method returns `null`. + */ + shareService(name: string): Promise; + + /** + * Stops providing a named service to guests. + * + * NOTE: Access to shared services may be restricted. + */ + unshareService(name: string): Promise; + + /** + * Gets a proxy for a named service provided by a Host. The service is + * available only while a Live Share session is active in the Guest role + * AND the session Host has shared the named service. + * + * The caller must add a notification handler to the returned `SharedService` + * instance in order to receive notifications from hosts. (Service proxies + * cannot receive requests, only send them.) + * + * A `SharedServiceProxy` instance is returned even if the service is not + * currently available (either because there is no active sharing session or + * because the Host has not shared the service). Listen to the event on the + * instance to be notified when the service becomes available or unavailable. + * + * NOTE: Access to shared services may be restricted. + * If the caller is not permitted, this method returns `null`. + */ + getSharedService(name: string): Promise; + + /** + * Converts a local `file:` URI to a `vsls:` URI. Only available in host role. + */ + convertLocalUriToShared(localUri: vscode.Uri): vscode.Uri; + + /** + * Converts a `vsls:` URI to a local `file:` URI. Only available in host role. + */ + convertSharedUriToLocal(sharedUri: vscode.Uri): vscode.Uri; + + /** + * Registers a command to be added to the Live Share contextual command palette. + * + * @param command command identifier, as declared in the calling extension's manifest + * @param isEnabled optional callback to check if the command is available + * @param thisArg optional `this` for the callback + * @returns Disposable that can be used to unregister the command, or null if the command + * could not be registered. + * + * The command must be declared in the `contributes.commands` section of the calling + * extension manifest, including extended VSLS label and detail properties, for example: + * "contributes": { + * "commands": [ + * { + * "command": "myextension.mycommand", + * "title": "Live Share: Do Something", + * "vsls-label": "$(star) Do Something", + * "vsls-detail": "Do some VSLS-related command provided by this extension" + * } + * ] + * } + * + * Extensions should use this capability judiciously, to avoid cluttering the Live Share + * command palette. If contributing a group of related commands, put them in a separate + * quick-pick menu that is brought up by a single command registered here. + * + * NOTE: Ability to contribute commands to the Live Share command palette may be restricted. + * If the caller is not permitted, this method returns `null`. + */ + registerCommand( + command: string, + isEnabled?: () => boolean, + thisArg?: any): vscode.Disposable | null; + + /** + * Registers a provider that can extend a Live Share tree view by providing additional items. + * + * @param viewId One of the Live Share tree view IDs. Not all Live Share tree views support + * data providers; currently only the session and session explorer views do. + * @param treeDataProvider A provider that provides additional data for the Live Share view. + * @returns Disposable that can be used to unregister the provider, or null if the provider + * could not be registered. + * + * NOTE: Ability to contribute commands to Live Share tree views may be restricted. If the + * caller is not permitted, this method returns `null`. + */ + registerTreeDataProvider( + viewId: View, + treeDataProvider: vscode.TreeDataProvider, + ): vscode.Disposable | null; + + /** + * Registers a contact service provider. + * + * @param name Name of the provider ('skype', 'teams',..) + * @param contactServiceProvider implementation of the ContactServiceProvider interface + * @returns Disposable that can be used to unregister the provider, or null if the provider + * could not be registered. + */ + registerContactServiceProvider( + name: string, + contactServiceProvider: ContactServiceProvider, + ): vscode.Disposable | null; + + /** + * Sends a request to share a local server in the active collaboration session. + * + * @param server Contains properties pertaining to the local server. + * @returns A registration object that will un-share the server when disposed. + */ + shareServer(server: Server): Promise; + + /** + * Request contacts to our presence providers + * @param emails Request contacts emails + */ + getContacts(emails: string[]): Promise; +} + +export interface ShareOptions { + /** + * Suppress display of the usual notification that indicates that sharing + * started. Also suppresses copying the join link to the clipboard. When + * setting this option, the caller should take care of showing or + * communicating the link somehow. + */ + suppressNotification?: boolean; + + /** + * (NOT IMPLEMENTED) Default access level for incoming guests. The host may + * override this setting on a per-guest basis. + */ + access?: Access; +} + +export interface JoinOptions { + /** + * Open the joined workspace in a new window, instead of re-using the current window. + */ + newWindow?: boolean; + correlationId?: string; +} + +/** + * Represents a local TCP server listening on the given port. + */ +export interface Server { + /** + * Local TCP port the server is listening on. + */ + port: number; + /** + * User-friendly name of the server. + */ + displayName?: string; + /** + * Default URL users will be redirected to when accessing the server. + */ + browseUrl?: string; +} + +export enum Role { + None = 0, + Host = 1, + Guest = 2, +} + +/** This is just a placeholder for a richer access control model to be added later. */ +export enum Access { + None = 0, + ReadOnly = 1, + ReadWrite = 3, + Owner = 0xFF, +} + +/** + * Authenticated Live Share user information. + * + * NOTE: Access to user information may be restricted. + * If the caller is not permitted, the `Peer.user` property returns 'null'. + */ +export interface UserInfo { + /** + * User display name. + */ + readonly displayName: string; + + /** + * Validated email address. + */ + readonly emailAddress: string | null; + + /** + * The username that the provider (e.g. GitHub) makes available. + */ + readonly userName: string | null; + + /** + * User id. This is persistent ID that stays the same for the same user + * if the user re-joins the session and even between sessions for some time. + */ + readonly id: string; +} + +/** + * Represents one participant in a sharing session. + */ +export interface Peer { + /** Integer that uniquely identifies a peer within the scope of a session. */ + readonly peerNumber: number; + + /** + * Authenticated Live Share user information. + * + * NOTE: Access to user information may be restricted. + * If the caller is not permitted, this property returns 'null'. + */ + readonly user: UserInfo | null; + + /** + * Role within the session. Each session has exactly one host; the rest of + * the peers are guests. + */ + readonly role: Role; + + /** + * Access level within the session. The host has full "owner" access to the + * session. Guests may have their access limited by the host. + */ + readonly access: Access; +} + +/** + * Information about the current session, including user information (in the base class). + */ +export interface Session extends Peer { + /** + * Globally unique identifier for the current session, or null if there is no active session. + */ + readonly id: string | null; +} + +export interface SessionChangeEvent { + readonly session: Session; +} + +export interface PeersChangeEvent { + readonly added: Peer[]; + readonly removed: Peer[]; +} + +export interface RequestHandler { + (args: any[], cancellation: vscode.CancellationToken): any | Promise; +} + +export interface NotifyHandler { + (args: object): void; +} + +/** + * A service that is provided by the host for use by guests. + */ +export interface SharedService { + /** A shared service is available when a sharing session is active as a Host. */ + readonly isServiceAvailable: boolean; + readonly onDidChangeIsServiceAvailable: vscode.Event; + + /** + * Registers a callback to be invoked when a request is sent to the service. + * + * @param name Request method name + */ + onRequest(name: string, handler: RequestHandler): void; + + /** + * Registers a callback to be invoked when a notification is sent to the service. + * + * @param name Notify event name + */ + onNotify(name: string, handler: NotifyHandler): void; + + /** + * Sends a notification (event) from the service. Does not wait for a response. + * + * If no sharing session is active, this method does nothing. + * + * @param name notify event name + * @param args notify event args object + */ + notify(name: string, args: object): void; +} + +/** + * A proxy that allows guests to access a host-provided service. + */ +export interface SharedServiceProxy { + /** + * A shared service proxy is available when a sharing session is active as a + * Guest, and the Host has shared a service with the same name. + */ + readonly isServiceAvailable: boolean; + readonly onDidChangeIsServiceAvailable: vscode.Event; + + /** + * Registers a callback to be invoked when a notification is sent by the service. + * + * @param name notify event name + */ + onNotify(name: string, handler: NotifyHandler): void; + + /** + * Sends a request (method call) to the service and waits for a response. + * + * @param name request method name + * + * @returns a promise that waits asynchronously for a response + * + * @throws SharedServiceProxyError if the service is not currently available + * (because there is no active sharing session or no peer has provided the service) + * + * @throws SharedServiceResponseError (via rejected promise) if the service's + * request handler throws an error + */ + request(name: string, args: any[], cancellation?: vscode.CancellationToken): Promise; + + /** + * Sends a notification (event) to the service. (Does not wait for a response.) + * + * If the service is not currently available (either because there is + * no active sharing session or because no peer has provided the service) + * then this method does nothing. + * + * @param name notify event name + * @param args notify event args object + */ + notify(name: string, args: object): void; +} + +/** + * Error thrown by a proxy when a request to a shared service cannot be made + * because the service is not available or cannot be reached. + */ +export interface SharedServiceProxyError extends Error { +} + +/** + * Error thrown by a proxy when a shared service's request handler threw an error. + * The remote message and remote stack are propagated back to the proxy. + */ +export interface SharedServiceResponseError extends Error { + remoteStack?: string; +} + +/** + * Identifiers for Live Share tree views. These identifiers may be used by other extensions + * to extend Live Share tree views with additional nodes via the `registerTreeDataProvider()` + * API. + */ +export enum View { + Session = 'liveshare.session', + ExplorerSession = 'liveshare.session.explorer', + Contacts = 'liveshare.contacts', + Help = 'liveshare.help', +} + +/** + * Identifiers for Live Share tree view items. These identifiers may be used by other + * extensions to extend Live Share tree items with additional commands using conditional + * expressions in the `view/item/context` section of their own package.json. + */ +export enum ViewItem { + // session item groups + Participants = 'participants', + Servers = 'servers', + Terminals = 'terminals', + + // participants + CurrentUser = 'participants.currentuser', // (not currently shown) + Guest = 'participants.guest', + FollowedGuest = 'participants.guest.followed', + Participant = 'participants.participant', + FollowedParticipant = 'participants.participant.followed', + + GuestAnonymous = 'participants.guest.anonymous', + FollowedGuestAnonymous = 'participants.guest.followed.anonymous', + + GuestElevated = 'participants.guest.elevated', + FollowedGuestElevated = 'participants.guest.followed.elevated', + + // servers + LocalServer = 'servers.local', + RemoteServer = 'servers.remote', + + // terminals + LocalTerminalReadOnly = 'terminals.local.readonly', + LocalTerminalReadWrite = 'terminals.local.readwrite', + RemoteTerminal = 'terminals.remote', + + // contacts + SuggestedContacts = 'contacts.suggested', + AvailableContacts = 'contacts.available', + ContactsProvider = 'contacts.provider', + SelfContact = 'contacts.selfContact', + Contact = 'contacts.contact', + ContactOffline = 'contacts.contact.offline', + RecentContact = 'contacts.recentContact', + RecentContactOffline = 'contacts.recentContact.offline', + NoContact = 'contacts.noContact', + RecentContacts = 'contacts.RecentContacts', + NoSuggestedContacts = 'contacts.NoSuggestedUsers', + NoRecentContacts = 'contacts.NoRecentContacts', + InvitedContact = 'contacts.invited', + + // help + SessionFeedbackQuestion = 'help.sessionFeedback', + ReportAProblem = 'help.reportAProblem', + TweetUsYourFeedback = 'help.tweetUsYourFeedback', + Survey = 'help.survey', + GoodFeedback = 'help.goodFeedback', + BadFeedback = 'help.badFeedback', + DontAskAgain = 'help.dontAskAgain', + Thankyou = 'help.thankyou', + MoreInfo = 'help.moreinfo', + + // Shown while session sharing / joining is in progress + Loading = 'loading', + + // Other / unspecified item type + Other = 'other', +} + +export interface InviteContactOptions { + + /** + * This option will force the invite to only use the email channel + */ + useEmail?: boolean; +} + +/** + * Represent a contact with live presence support + */ +export interface Contact { + readonly onDidChange: vscode.Event; + readonly id: string; + readonly email: string; + readonly displayName?: string; + readonly status?: string; + readonly avatarUri?: string; + + invite(options?: InviteContactOptions): Promise; +} + +/** + * Represent a collection of contacts that can be disposed at once + */ +export interface ContactsCollection { + readonly contacts: { [email: string]: Contact }; + dispose(): Promise; +} diff --git a/extensions/liveshare/src/main.ts b/extensions/liveshare/src/main.ts new file mode 100644 index 0000000000..a433f688f1 --- /dev/null +++ b/extensions/liveshare/src/main.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { GuestSessionManager } from './guestSessionManager'; +import { HostSessionManager } from './hostSessionManager'; + +declare var require: any; +let vsls = require('vsls'); + +export async function activate(context: vscode.ExtensionContext) { + const vslsApi = await vsls.getApi(); + if (!vslsApi) { + return; + } + + /* tslint:disable:no-unused-expression */ + new HostSessionManager(context, vslsApi); + new GuestSessionManager(context, vslsApi); + /* tslint:enable:no-unused-expression */ +} + +export function deactivate(): void { +} diff --git a/extensions/liveshare/src/providers/connectionProvider.ts b/extensions/liveshare/src/providers/connectionProvider.ts new file mode 100644 index 0000000000..f819beb716 --- /dev/null +++ b/extensions/liveshare/src/providers/connectionProvider.ts @@ -0,0 +1,215 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; +import * as constants from '../constants'; + +import { LiveShare, SharedService, SharedServiceProxy } from '../liveshare'; + +export class ConnectionProvider { + private _sharedService: SharedService; + private _sharedServiceProxy: SharedServiceProxy; + + protected _onConnect: vscode.EventEmitter = new vscode.EventEmitter(); + public readonly onConnect: vscode.Event = this._onConnect.event; + + protected _onDisconnect: vscode.EventEmitter = new vscode.EventEmitter(); + public readonly onDisconnect: vscode.Event = this._onDisconnect.event; + + protected _onConnectionChanged: vscode.EventEmitter = new vscode.EventEmitter(); + public readonly onConnectionChanged: vscode.Event = this._onConnectionChanged.event; + + private _onConnectionCompleteHandler: (connSummary: azdata.ConnectionInfoSummary) => any; + + public constructor( + private _isHost: boolean, + private _vslsApi: LiveShare, + service: SharedService | SharedServiceProxy) { + if (this._isHost) { + this._sharedService = service; + this.registerProviderListener(); + } else { + this._sharedServiceProxy = service; + this.registerProvider(); + } + } + + public registerProviderListener(): void { + let self = this; + azdata.connection.registerConnectionEventListener({ + onConnectionEvent(type: azdata.connection.ConnectionEventType, ownerUri: string, profile: azdata.IConnectionProfile) { + try { + let localUri: vscode.Uri = self._vslsApi.convertLocalUriToShared(vscode.Uri.parse(ownerUri)); + ownerUri = localUri.toString(); + } catch { + } + + self._sharedService.notify(type, { + ownerUri: ownerUri, + profile: profile + }); + } + }); + + this._sharedService.onRequest(constants.connectRequest, (args: any) => { + return; + }); + + this._sharedService.onRequest(constants.disconnectRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.cancelConnectRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.changeDatabaseRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.listDatabasesRequest, (args: any) => { + return true; + }); + this._sharedService.onRequest(constants.getConnectionStringRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.buildConnectionInfoRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.rebuildIntellisenseCacheRequest, (args: any) => { + return true; + }); + } + + public registerProvider(): vscode.Disposable { + const self = this; + this._sharedServiceProxy.onNotify('onConnect', (args: any) => { + this._onConnect.fire(args); + return args; + }); + + this._sharedServiceProxy.onNotify('onDisconnect', (args: any) => { + this._onDisconnect.fire(args); + return args; + }); + + this._sharedServiceProxy.onNotify('onConnectionChanged', (args: any) => { + this._onConnectionChanged.fire(args); + return args; + }); + + let connect = (ownerUri: string, connInfo: azdata.ConnectionInfo): Thenable => { + if (self._onConnectionCompleteHandler) { + // "test" liveshare connection details to be filled out in later iteration + let connSummary: azdata.ConnectionInfoSummary = { + ownerUri: ownerUri, + connectionId: ownerUri, + messages: undefined, + errorMessage: undefined, + errorNumber: undefined, + connectionSummary: { + serverName: connInfo.options['serverName'], + databaseName: connInfo.options['databaseName'], + userName: 'liveshare' + }, + serverInfo: { + serverMajorVersion: 1, + serverMinorVersion: 0, + serverReleaseVersion: 1, + engineEditionId: 1, + serverVersion: '1.0', + serverLevel: '1', + serverEdition: '1', + isCloud: false, + azureVersion: 1, + osVersion: '1', + options: connInfo.options + } + }; + self._onConnectionCompleteHandler(connSummary); + } + + return self._sharedServiceProxy.request(constants.connectRequest, [{ + ownerUri: ownerUri, + connInfo: connInfo + }]); + }; + + let disconnect = (ownerUri: string): Thenable => { + return self._sharedServiceProxy.request(constants.disconnectRequest, [{ + ownerUri: ownerUri + }]); + }; + + let cancelConnect = (ownerUri: string): Thenable => { + return self._sharedServiceProxy.request(constants.cancelConnectRequest, [{ + ownerUri: ownerUri + }]); + }; + + let changeDatabase = (ownerUri: string, newDatabase: string): Thenable => { + return self._sharedServiceProxy.request(constants.changeDatabaseRequest, [{ + ownerUri: ownerUri, + newDatabase: newDatabase + }]); + }; + + let listDatabases = (ownerUri: string): Thenable => { + return self._sharedServiceProxy.request(constants.listDatabasesRequest, [{ + ownerUri: ownerUri + }]); + }; + + let getConnectionString = (ownerUri: string, includePassword: boolean): Thenable => { + return self._sharedServiceProxy.request(constants.getConnectionStringRequest, [{ + ownerUri: ownerUri, + includePassword: includePassword + }]); + }; + + let buildConnectionInfo = (connectionString: string): Thenable => { + return self._sharedServiceProxy.request(constants.buildConnectionInfoRequest, [{ + connectionString: connectionString + }]); + }; + + let rebuildIntelliSenseCache = (ownerUri: string): Thenable => { + return self._sharedServiceProxy.request(constants.rebuildIntellisenseCacheRequest, [{ + ownerUri: ownerUri + }]); + }; + + let registerOnConnectionComplete = (handler: (connSummary: azdata.ConnectionInfoSummary) => any): void => { + self._onConnectionCompleteHandler = handler; + return; + }; + + let registerOnIntelliSenseCacheComplete = (handler: (connectionUri: string) => any): void => { + return; + }; + + let registerOnConnectionChanged = (handler: (changedConnInfo: azdata.ChangedConnectionInfo) => any): void => { + return; + }; + + return azdata.dataprotocol.registerConnectionProvider({ + providerId: constants.LiveShareProviderId, + connect, + disconnect, + cancelConnect, + changeDatabase, + listDatabases, + getConnectionString, + buildConnectionInfo, + rebuildIntelliSenseCache, + registerOnConnectionChanged, + registerOnIntelliSenseCacheComplete, + registerOnConnectionComplete + }); + } +} diff --git a/extensions/liveshare/src/providers/queryProvider.ts b/extensions/liveshare/src/providers/queryProvider.ts new file mode 100644 index 0000000000..88cd4e80a7 --- /dev/null +++ b/extensions/liveshare/src/providers/queryProvider.ts @@ -0,0 +1,233 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; + +import * as constants from '../constants'; +import { SharedService, SharedServiceProxy } from '../liveshare'; + +export class QueryProvider { + private _sharedService: SharedService; + private _sharedServiceProxy: SharedServiceProxy; + private _onQueryCompleteHandler: (result: azdata.QueryExecuteCompleteNotificationResult) => any; + + public constructor(private _isHost: boolean) { } + + public initialize(isHost: boolean, service: SharedService | SharedServiceProxy) { + if (this._isHost) { + this._sharedService = service; + this.registerProviderListener(); + } else { + this._sharedServiceProxy = service; + this.registerProvider(); + } + } + + public registerProviderListener() { + this._sharedService.onRequest(constants.cancelQueryRequest, (args: any) => { + return; + }); + + this._sharedService.onRequest(constants.runQueryRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.runQueryStatementRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.runQueryStringRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.runQueryAndReturnRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.parseSyntaxRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.getQueryRowsRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.disposeQueryRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.saveResultsRequest, (args: any) => { + return true; + }); + + this._sharedService.onRequest(constants.setQueryExecutionOptionsRequest, (args: any) => { + return true; + }); + } + + public registerProvider(): vscode.Disposable { + const self = this; + let runQuery = (ownerUri: string, querySelection: azdata.ISelectionData, executionPlanOptions?: azdata.ExecutionPlanOptions): Thenable => { + if (self._onQueryCompleteHandler) { + self._onQueryCompleteHandler({ + ownerUri: ownerUri, + batchSummaries: [] + }); + } + + return self._sharedServiceProxy.request(constants.runQueryRequest, [{ + ownerUri: ownerUri, + querySelection: querySelection, + executionPlanOptions: executionPlanOptions + }]); + }; + + let cancelQuery = (ownerUri: string): Thenable => { + return self._sharedServiceProxy.request(constants.cancelQueryRequest, [{ + ownerUri: ownerUri + }]); + }; + + let runQueryStatement = (ownerUri: string, line: number, column: number): Thenable => { + return self._sharedServiceProxy.request(constants.runQueryStatementRequest, [{ + ownerUri: ownerUri, + line: line, + column: column + }]); + }; + + let runQueryString = (ownerUri: string, query: string): Thenable => { + return self._sharedServiceProxy.request(constants.runQueryStringRequest, [{ + ownerUri: ownerUri, + query: query + }]); + }; + + let runQueryAndReturn = (ownerUri: string, queryString: string): Thenable => { + return self._sharedServiceProxy.request(constants.runQueryAndReturnRequest, [{ + ownerUri: ownerUri, + query: queryString + }]); + }; + + let parseSyntax = (ownerUri: string, query: string): Thenable => { + return self._sharedServiceProxy.request(constants.parseSyntaxRequest, [{ + ownerUri: ownerUri, + query: query + }]); + }; + + let getQueryRows = (rowData: azdata.QueryExecuteSubsetParams): Thenable => { + return self._sharedServiceProxy.request(constants.getQueryRowsRequest, [{ + rowData: rowData + }]); + }; + + let disposeQuery = (ownerUri: string): Thenable => { + return self._sharedServiceProxy.request(constants.disposeQueryRequest, [{ + ownerUri: ownerUri + }]); + }; + + let registerOnQueryComplete = (handler: (result: azdata.QueryExecuteCompleteNotificationResult) => any): void => { + self._onQueryCompleteHandler = handler; + }; + + let registerOnBatchStart = (handler: (batchInfo: azdata.QueryExecuteBatchNotificationParams) => any): void => { + }; + + let registerOnBatchComplete = (handler: (batchInfo: azdata.QueryExecuteBatchNotificationParams) => any): void => { + }; + + let registerOnResultSetAvailable = (handler: (resultSetInfo: azdata.QueryExecuteResultSetNotificationParams) => any): void => { + }; + + let registerOnResultSetUpdated = (handler: (resultSetInfo: azdata.QueryExecuteResultSetNotificationParams) => any): void => { + }; + + let registerOnMessage = (handler: (message: azdata.QueryExecuteMessageParams) => any): void => { + }; + + let saveResults = (requestParams: azdata.SaveResultsRequestParams): Thenable => { + return Promise.resolve(undefined); + }; + + let setQueryExecutionOptions = (ownerUri: string, options: azdata.QueryExecutionOptions): Thenable => { + return Promise.resolve(); + }; + + // Edit Data Requests + let commitEdit = (ownerUri: string): Thenable => { + return Promise.resolve(); + }; + + let createRow = (ownerUri: string): Thenable => { + return Promise.resolve(undefined); + }; + + let deleteRow = (ownerUri: string, rowId: number): Thenable => { + return Promise.resolve(); + }; + + let disposeEdit = (ownerUri: string): Thenable => { + return Promise.resolve(); + }; + + let initializeEdit = (ownerUri: string, schemaName: string, objectName: string, objectType: string, LimitResults: number, queryString: string): Thenable => { + return Promise.resolve(); + }; + + let revertCell = (ownerUri: string, rowId: number, columnId: number): Thenable => { + return Promise.resolve(undefined); + }; + + let revertRow = (ownerUri: string, rowId: number): Thenable => { + return Promise.resolve(); + }; + + let updateCell = (ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable => { + return Promise.resolve(undefined); + }; + + let getEditRows = (rowData: azdata.EditSubsetParams): Thenable => { + return Promise.resolve(undefined); + }; + + // Edit Data Event Handlers + let registerOnEditSessionReady = (handler: (ownerUri: string, success: boolean, message: string) => any): void => { + }; + + return azdata.dataprotocol.registerQueryProvider({ + providerId: constants.LiveShareProviderId, + cancelQuery, + commitEdit, + createRow, + deleteRow, + disposeEdit, + disposeQuery, + getEditRows, + getQueryRows, + setQueryExecutionOptions, + initializeEdit, + registerOnBatchComplete, + registerOnBatchStart, + registerOnEditSessionReady, + registerOnMessage, + registerOnQueryComplete, + registerOnResultSetAvailable, + registerOnResultSetUpdated, + revertCell, + revertRow, + runQuery, + runQueryAndReturn, + parseSyntax, + runQueryStatement, + runQueryString, + saveResults, + updateCell + }, true); + } +} diff --git a/extensions/liveshare/src/providers/statusProvider.ts b/extensions/liveshare/src/providers/statusProvider.ts new file mode 100644 index 0000000000..15a87eb82c --- /dev/null +++ b/extensions/liveshare/src/providers/statusProvider.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; +import { LiveShare, SharedService, SharedServiceProxy } from '../liveshare'; +import { ConnectionProvider } from './connectionProvider'; +import { LiveShareProviderId } from '../constants'; + +export class LiveShareDocumentState { + public isConnected: boolean; + public serverName?: string; + public databaseName?: string; +} + +export class StatusProvider { + private _sharedService: SharedService; + private _sharedServiceProxy: SharedServiceProxy; + + public constructor( + private _isHost: boolean, + private _vslsApi: LiveShare, + connectionProvider: ConnectionProvider, + service: SharedService | SharedServiceProxy) { + + if (this._isHost) { + this._sharedService = service; + this.registerStatusProvider(); + } else { + this._sharedServiceProxy = service; + + connectionProvider.onConnect(async (args: any) => { + if (args && args.ownerUri && args.profile) { + let queryDocument = await azdata.queryeditor.getQueryDocument(args.ownerUri); + if (queryDocument) { + let connectionOptions: Map = new Map(); + connectionOptions['providerName'] = LiveShareProviderId; + connectionOptions['serverName'] = args.profile.options['server']; + connectionOptions['databaseName'] = args.profile.options['database']; + connectionOptions['userName'] = 'liveshare'; + connectionOptions['password'] = 'liveshare'; + connectionOptions['authenticationType'] = 'liveshare'; + connectionOptions['savePassword'] = false; + connectionOptions['saveProfile'] = false; + let profile = azdata.connection.ConnectionProfile.createFrom(connectionOptions); + queryDocument.connect(profile); + } + } + }); + } + } + + private registerStatusProvider(): void { + let self = this; + + // Retrieves the current document state associated with the URI parameter. + // The URI will be in guest Live Share format and needs to be converted back + // to the host file path format. + this._sharedService.onRequest('getDocumentState', async (args: any[]) => { + if (args && args.length > 0) { + let ownerUri = vscode.Uri.parse(args[0].ownerUri); + let localUri: vscode.Uri = self._vslsApi.convertSharedUriToLocal(ownerUri); + let connection = await azdata.connection.getConnection(localUri.toString()); + + let serverName: string = 'liveshare'; + let databaseName: string = 'liveshare'; + if (connection) { + serverName = connection.serverName; + databaseName = connection.databaseName; + } + + let documentState: LiveShareDocumentState = { + isConnected: true, + serverName: serverName, + databaseName: databaseName + }; + return documentState; + } + return undefined; + }); + } + + public getDocumentState(doc: vscode.TextDocument): Promise { + if (!this._isHost) { + return this._sharedServiceProxy.request('getDocumentState', [{ + ownerUri: doc.uri.toString() + }]); + } else { + return Promise.resolve(undefined); + } + } +} diff --git a/extensions/liveshare/src/typings/refs.d.ts b/extensions/liveshare/src/typings/refs.d.ts new file mode 100644 index 0000000000..dad0d96412 --- /dev/null +++ b/extensions/liveshare/src/typings/refs.d.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// +/// +/// diff --git a/extensions/liveshare/tsconfig.json b/extensions/liveshare/tsconfig.json new file mode 100644 index 0000000000..a80576b9e2 --- /dev/null +++ b/extensions/liveshare/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../shared.tsconfig.json", + "compilerOptions": { + "outDir": "./out", + "strict": false, + "noUnusedParameters": false, + "noImplicitAny": false + }, + "include": [ + "src/**/*" + ] +} diff --git a/extensions/liveshare/yarn.lock b/extensions/liveshare/yarn.lock new file mode 100644 index 0000000000..634d7b2d47 --- /dev/null +++ b/extensions/liveshare/yarn.lock @@ -0,0 +1,1515 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" + integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@types/node@12.0.9": + version "12.0.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.9.tgz#18e0fc7bc6acc71f43a1a6ec9096c30d3954dd5c" + integrity sha512-xxrghIb6jMoEkNtdzGMUezwCEGuBd4QSA/Fko1XaUYpn6P/LwVw7UGpf4NzwGZXRC96fDgBJcBX7bXU0T52nWA== + +agent-base@4, agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + +ajv@^6.5.5: + version "6.10.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.1.tgz#ebf8d3af22552df9dd049bfbe50cc2390e823593" + integrity sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^2.0.0, chalk@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +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" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + +commander@^2.12.1: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +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= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.3.0": + version "0.3.0" + resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/21487d15a5f753ba885ce1e489abc0af03487544" + dependencies: + vscode-languageclient "3.5.1" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +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= + +diff@3.5.0, diff@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +enhanced-resolve@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + +errno@^0.1.3: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "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= + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +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= + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1, glob@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" + integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz#271ea8e90f836ac9f119daccd39c19ff7dfb0793" + integrity sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, 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== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +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= + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +loader-utils@^1.0.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +memory-fs@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + dependencies: + mime-db "1.40.0" + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +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= + dependencies: + minimist "0.0.8" + +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +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== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +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== + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +psl@^1.1.24: + version "1.2.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" + integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + +readable-stream@^2.0.1: + 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" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.3.2: + version "1.11.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" + integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== + dependencies: + path-parse "^1.0.6" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +safe-buffer@^5.0.1, safe-buffer@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +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-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +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" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.0.1, semver@^5.3.0, semver@^5.4.1: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.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" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.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" + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +ts-loader@^5.3.3: + version "5.4.5" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.4.5.tgz#a0c1f034b017a9344cef0961bfd97cc192492b8b" + integrity sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw== + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^3.1.4" + semver "^5.0.1" + +tslib@^1.8.0, tslib@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tslint@^5.12.1: + version "5.18.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.18.0.tgz#f61a6ddcf372344ac5e41708095bbf043a147ac6" + integrity sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w== + dependencies: + "@babel/code-frame" "^7.0.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^3.2.0" + glob "^7.1.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + mkdirp "^0.5.1" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.29.0" + +tsutils@^2.29.0: + version "2.29.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" + integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +typescript@^3.3.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" + integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse@^1.4.4: + version "1.4.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" + integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +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" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vscode-jsonrpc@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa" + integrity sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o= + +vscode-languageclient@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz#c78e582459c24e58f88020dfa34065e976186a98" + integrity sha512-GTQ+hSq/o4c/y6GYmyP9XNrVoIu0NFZ67KltSkqN+tO0eUNDIlrVNX+3DJzzyLhSsrctuGzuYWm3t87mNAcBmQ== + dependencies: + vscode-languageserver-protocol "3.5.1" + +vscode-languageserver-protocol@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz#5144a3a9eeccbd83fe2745bd4ed75fad6cc45f0d" + integrity sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA== + dependencies: + vscode-jsonrpc "3.5.0" + vscode-languageserver-types "3.5.0" + +vscode-languageserver-types@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374" + integrity sha1-5I15li8LjgLelV4/UkkI4rGcA3Q= + +vscode-test@^0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" + integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== + dependencies: + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + +vscode@^1.1.33: + version "1.1.35" + resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.35.tgz#f8c6beb905738b874d539ddb3784e5feeec71c0a" + integrity sha512-xPnxzQU40LOS2yPyzWW+WKpTV6qA3z16TcgpZ9O38UWLA157Zz4GxUx5H7Gd07pxzw0GqvusbF4D+5GBgNxvEQ== + dependencies: + glob "^7.1.2" + mocha "^5.2.0" + request "^2.88.0" + semver "^5.4.1" + source-map-support "^0.5.0" + url-parse "^1.4.4" + vscode-test "^0.4.1" + +vsls@^0.3.1291: + version "0.3.1291" + resolved "https://registry.yarnpkg.com/vsls/-/vsls-0.3.1291.tgz#55928c363b24d39a5d03d8e946ba85d7dcec3e38" + integrity sha512-8yJPN9p7k+XYyczOVtQmpun4K1CRDsw/hdnIzT/c40r5bIkpptfsBlHmmLemoIV+CAHvrTLdWKEf5OtRvdcn9A== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/product.json b/product.json index 43b3bf938e..0f2f1c43a2 100644 --- a/product.json +++ b/product.json @@ -59,6 +59,28 @@ "msrvida.azdata-sanddance" ] }, + "extensionAllowedProposedApi": [ + "ms-vscode.references-view", + "ms-vsliveshare.vsliveshare", + "ms-vsliveshare.cloudenv", + "ms-vsliveshare.cloudenv-explorer", + "GitHub.vscode-pull-request-github", + "GitHub.vscode-pull-request-github-insiders", + "Microsoft.vscode-nmake-tools", + "ms-vscode-remote.remote-containers", + "ms-vscode-remote.remote-containers-nightly", + "ms-vscode-remote.remote-ssh", + "ms-vscode-remote.remote-ssh-nightly", + "ms-vscode-remote.remote-ssh-edit", + "ms-vscode-remote.remote-ssh-edit-nightly", + "ms-vscode-remote.remote-ssh-explorer", + "ms-vscode-remote.remote-ssh-explorer-nightly", + "ms-vscode-remote.remote-wsl", + "ms-vscode-remote.remote-wsl-nightly", + "ms-vscode-remote.vscode-remote-extensionpack", + "ms-vscode-remote.vscode-remote-extensionpack-nightly", + "ms-azuretools.vscode-docker" + ], "extensionsGallery": { "serviceUrl": "https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json" } diff --git a/src/sql/azdata.d.ts b/src/sql/azdata.d.ts index ee87e34fc6..89a44748ed 100644 --- a/src/sql/azdata.d.ts +++ b/src/sql/azdata.d.ts @@ -33,7 +33,7 @@ declare module 'azdata' { export function registerMetadataProvider(provider: MetadataProvider): vscode.Disposable; - export function registerQueryProvider(provider: QueryProvider): vscode.Disposable; + export function registerQueryProvider(provider: QueryProvider, isLiveShare?: boolean): vscode.Disposable; export function registerAdminServicesProvider(provider: AdminServicesProvider): vscode.Disposable; @@ -93,7 +93,7 @@ declare module 'azdata' { azureTenantId?: string; options: { [name: string]: any }; - static createFrom(options: any[]): ConnectionProfile; + static createFrom(options: Map): ConnectionProfile; } /** @@ -3825,6 +3825,9 @@ declare module 'azdata' { // tab content is build using the modelview UI builder APIs // probably should rename DialogTab class since it is useful outside dialogs createQueryTab(tab: window.DialogTab): void; + + // connect the query document using the given connection profile + connect(connectionProfile: connection.ConnectionProfile): Thenable; } /** diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 44b8419468..5c5de52279 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -25,6 +25,8 @@ declare module 'azdata' { * Register a connection event listener */ export function registerConnectionEventListener(listener: connection.ConnectionEventListener): void; + + export function getConnection(uri: string): Thenable; } diff --git a/src/sql/platform/connection/common/connectionManagement.ts b/src/sql/platform/connection/common/connectionManagement.ts index 504b4a4d24..b016f78267 100644 --- a/src/sql/platform/connection/common/connectionManagement.ts +++ b/src/sql/platform/connection/common/connectionManagement.ts @@ -277,6 +277,8 @@ export interface IConnectionManagementService { * @returns array of connections */ getConnections(activeConnectionsOnly?: boolean): ConnectionProfile[]; + + getConnection(uri: string): ConnectionProfile; } export enum RunQueryOnConnectionMode { diff --git a/src/sql/platform/connection/common/connectionManagementService.ts b/src/sql/platform/connection/common/connectionManagementService.ts index aebe5852a6..f078bccbbb 100644 --- a/src/sql/platform/connection/common/connectionManagementService.ts +++ b/src/sql/platform/connection/common/connectionManagementService.ts @@ -156,8 +156,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti return this._onLanguageFlavorChanged.event; } - private _providerCount: number = 0; - // Connection Provider Registration public registerProvider(providerId: string, provider: azdata.ConnectionProvider): void { if (!this._providers.has(providerId)) { @@ -1337,7 +1335,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti * @returns array of connections **/ public getConnections(activeConnectionsOnly?: boolean): ConnectionProfile[] { - // 1. Active Connections const connections = this.getActiveConnections(); @@ -1368,6 +1365,20 @@ export class ConnectionManagementService extends Disposable implements IConnecti return connections; } + public getConnection(uri: string): ConnectionProfile { + const connections = this.getActiveConnections(); + if (connections) { + for (let connection of connections) { + let connectionUri = this.getConnectionUriFromId(connection.id); + if (connectionUri === uri) { + return connection; + } + } + } + + return undefined; + } + private getConnectionsInGroup(group: ConnectionProfileGroup): ConnectionProfile[] { const connections = []; if (group) { diff --git a/src/sql/platform/connection/common/connectionProfile.ts b/src/sql/platform/connection/common/connectionProfile.ts index dcf6af4afd..a526cf616a 100644 --- a/src/sql/platform/connection/common/connectionProfile.ts +++ b/src/sql/platform/connection/common/connectionProfile.ts @@ -33,8 +33,7 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa public constructor( capabilitiesService: ICapabilitiesService, - model: string | azdata.IConnectionProfile - ) { + model: string | azdata.IConnectionProfile) { super(capabilitiesService, model); if (model && !isString(model)) { this.groupId = model.groupId; diff --git a/src/sql/platform/connection/common/connectionStatusManager.ts b/src/sql/platform/connection/common/connectionStatusManager.ts index b7e0a65063..b70d6c04bb 100644 --- a/src/sql/platform/connection/common/connectionStatusManager.ts +++ b/src/sql/platform/connection/common/connectionStatusManager.ts @@ -189,7 +189,14 @@ export class ConnectionStatusManager { return undefined; } + private isSharedSession(fileUri: string): boolean { + return fileUri && fileUri.startsWith('vsls:'); + } + public isConnected(id: string): boolean { + if (this.isSharedSession(id)) { + return true; + } return (id in this._connections && this._connections[id].connectionId && !!this._connections[id].connectionId); } diff --git a/src/sql/platform/connection/common/providerConnectionInfo.ts b/src/sql/platform/connection/common/providerConnectionInfo.ts index c992ad1536..1d183d288f 100644 --- a/src/sql/platform/connection/common/providerConnectionInfo.ts +++ b/src/sql/platform/connection/common/providerConnectionInfo.ts @@ -70,7 +70,7 @@ export class ProviderConnectionInfo extends Disposable implements azdata.Connect public set providerName(name: string) { this._providerName = name; - if (!this._serverCapabilities) { + if (!this._serverCapabilities && this.capabilitiesService) { let capabilities = this.capabilitiesService.getCapabilities(this.providerName); if (capabilities) { this._serverCapabilities = capabilities.connection; @@ -192,6 +192,11 @@ export class ProviderConnectionInfo extends Disposable implements azdata.Connect } public isPasswordRequired(): boolean { + // if there is no provider capabilities metadata assume a password is not required + if (!this._serverCapabilities) { + return false; + } + let optionMetadata = this._serverCapabilities.connectionOptions.find( option => option.specialValueType === ConnectionOptionSpecialType.password); let isPasswordRequired: boolean = optionMetadata.isRequired; diff --git a/src/sql/platform/connection/test/common/testConnectionManagementService.ts b/src/sql/platform/connection/test/common/testConnectionManagementService.ts index 3dba72ab8b..74449cab99 100644 --- a/src/sql/platform/connection/test/common/testConnectionManagementService.ts +++ b/src/sql/platform/connection/test/common/testConnectionManagementService.ts @@ -294,4 +294,8 @@ export class TestConnectionManagementService implements IConnectionManagementSer getConnections(activeConnectionsOnly?: boolean): ConnectionProfile[] { return []; } + + getConnection(uri: string): ConnectionProfile { + return undefined; + } } diff --git a/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts b/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts index ce557f4dec..ae60e5365d 100644 --- a/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts +++ b/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts @@ -82,6 +82,31 @@ export class MainThreadConnectionManagement extends Disposable implements MainTh return Promise.resolve(this._connectionManagementService.getConnections(activeConnectionsOnly).map(profile => this.convertToConnectionProfile(profile))); } + public $getConnection(uri: string): Thenable { + let profile = this._connectionManagementService.getConnection(uri); + if (!profile) { + return Promise.resolve(undefined); + } + + let connection: azdata.connection.ConnectionProfile = { + providerId: profile.providerName, + connectionId: profile.id, + connectionName: profile.connectionName, + serverName: profile.serverName, + databaseName: profile.databaseName, + userName: profile.userName, + password: profile.password, + authenticationType: profile.authenticationType, + savePassword: profile.savePassword, + groupFullName: profile.groupFullName, + groupId: profile.groupId, + saveProfile: profile.savePassword, + azureTenantId: profile.azureTenantId, + options: profile.options + }; + return Promise.resolve(connection); + } + public $getActiveConnections(): Thenable { return Promise.resolve(this._connectionManagementService.getActiveConnections().map(profile => this.convertConnection(profile))); } diff --git a/src/sql/workbench/api/browser/mainThreadQueryEditor.ts b/src/sql/workbench/api/browser/mainThreadQueryEditor.ts index 923bafe190..750549a6df 100644 --- a/src/sql/workbench/api/browser/mainThreadQueryEditor.ts +++ b/src/sql/workbench/api/browser/mainThreadQueryEditor.ts @@ -13,6 +13,8 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import * as azdata from 'azdata'; import { IQueryManagementService } from 'sql/platform/query/common/queryManagement'; +import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; +import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; @extHostNamedCustomer(SqlMainContext.MainThreadQueryEditor) export class MainThreadQueryEditor extends Disposable implements MainThreadQueryEditorShape { @@ -62,6 +64,36 @@ export class MainThreadQueryEditor extends Disposable implements MainThreadQuery }); } + private static connectionProfileToIConnectionProfile(connection: azdata.connection.ConnectionProfile): IConnectionProfile { + let profile: ConnectionProfile = new ConnectionProfile(undefined, undefined); + profile.options = connection.options; + profile.providerName = connection.options['providerName']; + return profile.toIConnectionProfile(); + } + + public $connectWithProfile(fileUri: string, connection: azdata.connection.ConnectionProfile): Thenable { + return new Promise(async (resolve, reject) => { + let editors = this._editorService.visibleControls.filter(resource => { + return !!resource && resource.input.getResource().toString() === fileUri; + }); + let editor = editors && editors.length > 0 ? editors[0] : undefined; + + let options: IConnectionCompletionOptions = { + params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: editor ? editor.input as any : undefined }, + saveTheConnection: false, + showDashboard: false, + showConnectionDialogOnError: false, + showFirewallRuleOnError: false, + }; + + let profile: IConnectionProfile = MainThreadQueryEditor.connectionProfileToIConnectionProfile(connection); + let connectionResult = await this._connectionManagementService.connect(profile, fileUri, options); + if (connectionResult && connectionResult.connected) { + console.log(`editor ${fileUri} connected`); + } + }); + } + public $runQuery(fileUri: string, runCurrentQuery: boolean = true): void { let filteredEditors = this._editorService.visibleControls.filter(editor => editor.input.getResource().toString() === fileUri); if (filteredEditors && filteredEditors.length > 0) { diff --git a/src/sql/workbench/api/common/extHostConnectionManagement.ts b/src/sql/workbench/api/common/extHostConnectionManagement.ts index 708e6a0c03..9779248adf 100644 --- a/src/sql/workbench/api/common/extHostConnectionManagement.ts +++ b/src/sql/workbench/api/common/extHostConnectionManagement.ts @@ -20,10 +20,6 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap this._proxy = mainContext.getProxy(SqlMainContext.MainThreadConnectionManagement); } - public $getCurrentConnection(): Thenable { - return this._proxy.$getCurrentConnectionProfile(); - } - public $onConnectionEvent(handle: number, type: azdata.connection.ConnectionEventType, ownerUri: string, profile: azdata.IConnectionProfile): void { let listener = this._connectionListeners[handle]; if (listener) { @@ -37,10 +33,18 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap this._nextListenerHandle++; } + public $getCurrentConnection(): Thenable { + return this._proxy.$getCurrentConnectionProfile(); + } + public $getConnections(activeConnectionsOnly?: boolean): Thenable { return this._proxy.$getConnections(activeConnectionsOnly); } + public $getConnection(uri: string): Thenable { + return this._proxy.$getConnection(uri); + } + // "sqlops" back-compat connection APIs public $getActiveConnections(): Thenable { return this._proxy.$getActiveConnections(); diff --git a/src/sql/workbench/api/common/extHostDataProtocol.ts b/src/sql/workbench/api/common/extHostDataProtocol.ts index e51b758f3e..72d6db0e67 100644 --- a/src/sql/workbench/api/common/extHostDataProtocol.ts +++ b/src/sql/workbench/api/common/extHostDataProtocol.ts @@ -251,6 +251,7 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape { if (this.uriTransformer) { ownerUri = URI.from(this.uriTransformer.transformIncoming(URI.parse(ownerUri))).toString(true); } + return this._resolveProvider(handle).runQuery(ownerUri, selection, runOptions); } @@ -274,6 +275,10 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape { } } + $connectWithProfile(handle: number, ownerUri: string, profile: azdata.connection.ConnectionProfile): Thenable { + return new Promise((r) => r()); + } + $parseSyntax(handle: number, ownerUri: string, query: string): Thenable { return this._resolveProvider(handle).parseSyntax(ownerUri, query); } diff --git a/src/sql/workbench/api/common/extHostQueryEditor.ts b/src/sql/workbench/api/common/extHostQueryEditor.ts index f91c9f1f36..0d2c560e8d 100644 --- a/src/sql/workbench/api/common/extHostQueryEditor.ts +++ b/src/sql/workbench/api/common/extHostQueryEditor.ts @@ -26,6 +26,10 @@ class ExtHostQueryDocument implements azdata.queryeditor.QueryDocument { public createQueryTab(tab: azdata.window.DialogTab): void { this._proxy.$createQueryTab(this.uri, tab.title, tab.content); } + + public connect(connectionProfile: azdata.connection.ConnectionProfile): Thenable { + return this._proxy.$connectWithProfile(this.uri, connectionProfile); + } } export class ExtHostQueryEditor implements ExtHostQueryEditorShape { diff --git a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts index de541f42c6..af49d26293 100644 --- a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts +++ b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts @@ -118,7 +118,9 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp registerConnectionEventListener(listener: azdata.connection.ConnectionEventListener): void { return extHostConnectionManagement.$registerConnectionEventListener(mssqlProviderName, listener); }, - + getConnection(uri: string): Thenable { + return extHostConnectionManagement.$getConnection(uri); + }, // "sqlops" back-compat APIs getActiveConnections(): Thenable { console.warn('the method azdata.connection.getActiveConnections has been deprecated, replace it with azdata.connection.getConnections'); diff --git a/src/sql/workbench/api/common/sqlExtHost.protocol.ts b/src/sql/workbench/api/common/sqlExtHost.protocol.ts index 6fb79e8946..dd8767125e 100644 --- a/src/sql/workbench/api/common/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/common/sqlExtHost.protocol.ts @@ -180,6 +180,11 @@ export abstract class ExtHostDataProtocolShape { */ $setQueryExecutionOptions(handle: number, ownerUri: string, options: azdata.QueryExecutionOptions): Thenable { throw ni(); } + /** + * Connect the editor document to the given profile + */ + $connectWithProfile(handle: number, ownerUri: string, profile: azdata.connection.ConnectionProfile): Thenable { throw ni(); } + /** * Disposes the cached information regarding a query */ @@ -578,6 +583,7 @@ export interface MainThreadDataProtocolShape extends IDisposable { export interface MainThreadConnectionManagementShape extends IDisposable { $registerConnectionEventListener(handle: number, providerId: string): void; $getConnections(activeConnectionsOnly?: boolean): Thenable; + $getConnection(uri: string): Thenable; $getActiveConnections(): Thenable; $getCurrentConnection(): Thenable; $getCurrentConnectionProfile(): Thenable; @@ -780,6 +786,7 @@ export interface ExtHostQueryEditorShape { export interface MainThreadQueryEditorShape extends IDisposable { $connect(fileUri: string, connectionId: string): Thenable; + $connectWithProfile(fileUri: string, connectionProfile: azdata.connection.ConnectionProfile): Thenable; $runQuery(fileUri: string, runCurrentQuery?: boolean): void; $createQueryTab(fileUri: string, title: string, content: string): void; $setQueryExecutionOptions(fileUri: string, options: azdata.QueryExecutionOptions): Thenable; diff --git a/src/sql/workbench/api/common/sqlExtHostTypes.ts b/src/sql/workbench/api/common/sqlExtHostTypes.ts index 7fe3e92845..0129993ce5 100644 --- a/src/sql/workbench/api/common/sqlExtHostTypes.ts +++ b/src/sql/workbench/api/common/sqlExtHostTypes.ts @@ -564,25 +564,116 @@ export interface ISingleNotebookEditOperation { } export class ConnectionProfile { + get providerId(): string { + return this.options['providerId']; + } - providerId: string; - connectionId: string; - connectionName: string; - serverName: string; - databaseName: string; - userName: string; - password: string; - authenticationType: string; - savePassword: boolean; - groupFullName: string; - groupId: string; - saveProfile: boolean; - azureTenantId?: string; - options: { [name: string]: any }; + set providerId(value: string) { + this.options['providerId'] = value; + } - static createFrom(options: any[]): ConnectionProfile { - // create from options - return undefined; + get connectionId(): string { + return this.options['connectionId']; + } + + set connectionId(value: string) { + this.options['connectionId'] = value; + } + + get connectionName(): string { + return this.options['connectionName']; + } + + set connectionName(value: string) { + this.options['connectionName'] = value; + } + + get serverName(): string { + return this.options['serverName']; + } + + set serverName(value: string) { + this.options['serverName'] = value; + } + + get databaseName(): string { + return this.options['databaseName']; + } + + set databaseName(value: string) { + this.options['databaseName'] = value; + } + + get userName(): string { + return this.options['userName']; + } + + set userName(value: string) { + this.options['userName'] = value; + } + + get password(): string { + return this.options['password']; + } + + set password(value: string) { + this.options['password'] = value; + } + + get authenticationType(): string { + return this.options['authenticationType']; + } + + set authenticationType(value: string) { + this.options['authenticationType'] = value; + } + + get savePassword(): boolean { + return this.options['savePassword']; + } + + set savePassword(value: boolean) { + this.options['savePassword'] = value; + } + + get groupFullName(): string { + return this.options['groupFullName']; + } + + set groupFullName(value: string) { + this.options['groupFullName'] = value; + } + + get groupId(): string { + return this.options['groupId']; + } + + set groupId(value: string) { + this.options['groupId'] = value; + } + + get saveProfile(): boolean { + return this.options['groupId']; + } + + set saveProfile(value: boolean) { + this.options['groupId'] = value; + } + + get azureTenantId(): string { + return this.options['azureTenantId']; + } + + set azureTenantId(value: string) { + this.options['azureTenantId'] = value; + } + + options: Map = new Map(); + + static createFrom(options: Map): ConnectionProfile { + let profile = new ConnectionProfile(); + profile.options = options; + return profile; } } diff --git a/src/sql/workbench/parts/query/browser/queryActions.ts b/src/sql/workbench/parts/query/browser/queryActions.ts index 614733f29b..35a1928f8b 100644 --- a/src/sql/workbench/parts/query/browser/queryActions.ts +++ b/src/sql/workbench/parts/query/browser/queryActions.ts @@ -472,12 +472,14 @@ export class ToggleConnectDatabaseAction extends QueryTaskbarAction { } public run(): Promise { - if (this.connected) { - // Call disconnectEditor regardless of the connection state and let the ConnectionManagementService - // determine if we need to disconnect, cancel an in-progress connection, or do nothing - this.connectionManagementService.disconnectEditor(this.editor.input); - } else { - this.connectEditor(this.editor); + if (!this.editor.input.isSharedSession) { + if (this.connected) { + // Call disconnectEditor regardless of the connection state and let the ConnectionManagementService + // determine if we need to disconnect, cancel an in-progress connection, or do nothing + this.connectionManagementService.disconnectEditor(this.editor.input); + } else { + this.connectEditor(this.editor); + } } return Promise.resolve(null); } diff --git a/src/sql/workbench/parts/query/common/queryInput.ts b/src/sql/workbench/parts/query/common/queryInput.ts index b9c8d75dfd..fb4523a164 100644 --- a/src/sql/workbench/parts/query/common/queryInput.ts +++ b/src/sql/workbench/parts/query/common/queryInput.ts @@ -355,4 +355,8 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec public get tabColor(): string { return this._connectionManagementService.getTabColorForUri(this.uri); } + + public get isSharedSession(): boolean { + return this.uri && this.uri.startsWith('vsls:'); + } }