Azure: add PostgresSQL support and refactor to use resource graph (#8046)

* Azure: add PostgresSQL support and refactor to use resource graph
- Refactored to use @azure/arm-resourcegraph for all queries
- Refactored database lookup to do just 2 queries
(all servers, all DBS) instead of waiting serially on 1 query per RG
- Added Azure Database for PostgresSQL Servers support in the tree
- Removed use of older azure APIs in preference to ones compatible with resource graph
- Note: Had to use v1.0 of new subscriptions package because resourcegraph is 2month out of date vs all other packages
This commit is contained in:
Kevin Cunnane
2019-10-28 09:47:38 -07:00
committed by GitHub
parent a7f597c943
commit 067af76904
21 changed files with 565 additions and 176 deletions

View File

@@ -15,7 +15,8 @@ module.exports = withDefaults({
extension: './src/extension.ts' extension: './src/extension.ts'
}, },
externals: { externals: {
'ms-rest': 'commonjs ms-rest', '@azure/ms-rest-azure-js': 'commonjs @azure/ms-rest-azure-js',
'@azure/ms-rest-js': 'commonjs @azure/ms-rest-js',
'request': 'commonjs request' 'request': 'commonjs request'
} }
}); });

View File

@@ -173,10 +173,9 @@
"hasAzureResourceProviders": true "hasAzureResourceProviders": true
}, },
"dependencies": { "dependencies": {
"@azure/arm-resourcegraph": "^2.0.0",
"@azure/arm-subscriptions": "1.0.0",
"adal-node": "^0.1.28", "adal-node": "^0.1.28",
"azure-arm-resource": "^7.0.0",
"azure-arm-sql": "^5.0.1",
"ms-rest": "^2.5.0",
"request": "2.88.0", "request": "2.88.0",
"vscode-nls": "^4.0.0" "vscode-nls": "^4.0.0"
}, },
@@ -184,9 +183,9 @@
"@types/mocha": "^5.2.5", "@types/mocha": "^5.2.5",
"@types/node": "^10.12.12", "@types/node": "^10.12.12",
"@types/request": "^2.48.1", "@types/request": "^2.48.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0", "mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7", "mocha-multi-reporters": "^1.1.7",
"mocha": "^5.2.0",
"should": "^13.2.1", "should": "^13.2.1",
"typemoq": "^2.1.0", "typemoq": "^2.1.0",
"vscode": "1.1.26" "vscode": "1.1.26"

View File

@@ -6,11 +6,11 @@
import { window, QuickPickItem } from 'vscode'; import { window, QuickPickItem } from 'vscode';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from '@azure/ms-rest-js';
import { AppContext } from '../appContext';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
import { AppContext } from '../appContext';
import { azureResource } from './azure-resource'; import { azureResource } from './azure-resource';
import { TreeNode } from './treeNode'; import { TreeNode } from './treeNode';
import { AzureResourceCredentialError } from './errors'; import { AzureResourceCredentialError } from './errors';
@@ -46,7 +46,11 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur
} }
} }
let selectedSubscriptions = (await subscriptionFilterService.getSelectedSubscriptions(accountNode.account)) || <azureResource.AzureResourceSubscription[]>[]; let selectedSubscriptions = await subscriptionFilterService.getSelectedSubscriptions(accountNode.account);
if (!selectedSubscriptions) {
selectedSubscriptions = [];
}
const selectedSubscriptionIds: string[] = []; const selectedSubscriptionIds: string[] = [];
if (selectedSubscriptions.length > 0) { if (selectedSubscriptions.length > 0) {
selectedSubscriptionIds.push(...selectedSubscriptions.map((subscription) => subscription.id)); selectedSubscriptionIds.push(...selectedSubscriptions.map((subscription) => subscription.id));
@@ -67,9 +71,9 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur
}; };
}).sort((a, b) => a.label.localeCompare(b.label)); }).sort((a, b) => a.label.localeCompare(b.label));
const selectedSubscriptionQuickPickItems = (await window.showQuickPick(subscriptionQuickPickItems, { canPickMany: true })); const selectedSubscriptionQuickPickItems = await window.showQuickPick(subscriptionQuickPickItems, { canPickMany: true });
if (selectedSubscriptionQuickPickItems && selectedSubscriptionQuickPickItems.length > 0) { if (selectedSubscriptionQuickPickItems && selectedSubscriptionQuickPickItems.length > 0) {
tree.refresh(node, false); await tree.refresh(node, false);
selectedSubscriptions = selectedSubscriptionQuickPickItems.map((subscriptionItem) => subscriptionItem.subscription); selectedSubscriptions = selectedSubscriptionQuickPickItems.map((subscriptionItem) => subscriptionItem.subscription);
await subscriptionFilterService.saveSelectedSubscriptions(accountNode.account, selectedSubscriptions); await subscriptionFilterService.saveSelectedSubscriptions(accountNode.account, selectedSubscriptions);
@@ -79,7 +83,7 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur
appContext.apiWrapper.registerCommand('azure.resource.refreshall', () => tree.notifyNodeChanged(undefined)); appContext.apiWrapper.registerCommand('azure.resource.refreshall', () => tree.notifyNodeChanged(undefined));
appContext.apiWrapper.registerCommand('azure.resource.refresh', async (node?: TreeNode) => { appContext.apiWrapper.registerCommand('azure.resource.refresh', async (node?: TreeNode) => {
tree.refresh(node, true); await tree.refresh(node, true);
}); });
appContext.apiWrapper.registerCommand('azure.resource.signin', async (node?: TreeNode) => { appContext.apiWrapper.registerCommand('azure.resource.signin', async (node?: TreeNode) => {

View File

@@ -3,9 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; import * as msRest from '@azure/ms-rest-js';
import { ServiceClientCredentials } from 'ms-rest';
import { Account, DidChangeAccountsParams } from 'azdata'; import { Account, DidChangeAccountsParams } from 'azdata';
import { Event } from 'vscode'; import { Event } from 'vscode';
@@ -13,17 +12,15 @@ import { azureResource } from './azure-resource';
export interface IAzureResourceAccountService { export interface IAzureResourceAccountService {
getAccounts(): Promise<Account[]>; getAccounts(): Promise<Account[]>;
readonly onDidChangeAccounts: Event<DidChangeAccountsParams>; readonly onDidChangeAccounts: Event<DidChangeAccountsParams>;
} }
export interface IAzureResourceSubscriptionService { export interface IAzureResourceSubscriptionService {
getSubscriptions(account: Account, credential: ServiceClientCredentials): Promise<azureResource.AzureResourceSubscription[]>; getSubscriptions(account: Account, credential: msRest.ServiceClientCredentials): Promise<azureResource.AzureResourceSubscription[]>;
} }
export interface IAzureResourceSubscriptionFilterService { export interface IAzureResourceSubscriptionFilterService {
getSelectedSubscriptions(account: Account): Promise<azureResource.AzureResourceSubscription[]>; getSelectedSubscriptions(account: Account): Promise<azureResource.AzureResourceSubscription[]>;
saveSelectedSubscriptions(account: Account, selectedSubscriptions: azureResource.AzureResourceSubscription[]): Promise<void>; saveSelectedSubscriptions(account: Account, selectedSubscriptions: azureResource.AzureResourceSubscription[]): Promise<void>;
} }
@@ -50,7 +47,7 @@ export interface AzureSqlResource {
} }
export interface IAzureResourceService<T extends AzureSqlResource> { export interface IAzureResourceService<T extends AzureSqlResource> {
getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise<T[]>; getResources(subscription: azureResource.AzureResourceSubscription, credential: msRest.ServiceClientCredentials): Promise<T[]>;
} }
@@ -60,6 +57,7 @@ export interface AzureResourceDatabase extends AzureSqlResource {
} }
export interface AzureResourceDatabaseServer extends AzureSqlResource { export interface AzureResourceDatabaseServer extends AzureSqlResource {
id?: string;
fullName: string; fullName: string;
defaultDatabaseName: string; defaultDatabaseName: string;
} }

View File

@@ -3,35 +3,56 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ServiceClientCredentials } from 'ms-rest'; import { ServiceClientCredentials } from '@azure/ms-rest-js';
import { SqlManagementClient } from 'azure-arm-sql';
import { azureResource } from '../../azure-resource'; import { azureResource } from '../../azure-resource';
import { IAzureResourceService, AzureResourceDatabase } from '../../interfaces'; import { IAzureResourceService, AzureResourceDatabase } from '../../interfaces';
import { serversQuery, DbServerGraphData } from '../databaseServer/databaseServerService';
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
interface DatabaseGraphData extends GraphData {
kind: string;
}
export class AzureResourceDatabaseService implements IAzureResourceService<AzureResourceDatabase> { export class AzureResourceDatabaseService implements IAzureResourceService<AzureResourceDatabase> {
public async getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise<AzureResourceDatabase[]> { public async getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise<AzureResourceDatabase[]> {
const databases: AzureResourceDatabase[] = []; const databases: AzureResourceDatabase[] = [];
const sqlManagementClient = new SqlManagementClient(credential, subscription.id); const resourceClient = new ResourceGraphClient(credential);
const svrs = await sqlManagementClient.servers.list();
for (const svr of svrs) { // Query servers and databases in parallel (start both promises before waiting on the 1st)
// Extract resource group name from svr.id let serverQueryPromise = queryGraphResources<GraphData>(resourceClient, subscription.id, serversQuery);
const svrIdRegExp = new RegExp(`\/subscriptions\/${subscription.id}\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/${svr.name}`); let dbQueryPromise = queryGraphResources<GraphData>(resourceClient, subscription.id, 'where type == "microsoft.sql/servers/databases"');
if (!svrIdRegExp.test(svr.id)) { let servers: DbServerGraphData[] = await serverQueryPromise as DbServerGraphData[];
continue; let dbByGraph: DatabaseGraphData[] = await dbQueryPromise as DatabaseGraphData[];
// Group servers by resource group, then merge DB results with servers so we
// can get the login name and server fully qualified name to use for connections
let rgMap = new Map<string, DbServerGraphData[]>();
servers.forEach(s => {
let serversForRg = rgMap.get(s.resourceGroup) || [];
serversForRg.push(s);
rgMap.set(s.resourceGroup, serversForRg);
});
// Match database ID. When calling exec [0] is full match, [1] is resource group name, [2] is server name
const svrIdRegExp = new RegExp(`\/subscriptions\/${subscription.id}\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/(.+)\/databases\/.+`);
dbByGraph.forEach(db => {
// Filter master DBs, and for all others find their server to get login info
let serversForRg = rgMap.get(db.resourceGroup);
if (serversForRg && !db.kind.endsWith('system') && svrIdRegExp.test(db.id)) {
const founds = svrIdRegExp.exec(db.id);
const serverName = founds[2];
let server = servers.find(s => s.name === serverName);
if (server) {
databases.push({
name: db.name,
serverName: server.name,
serverFullName: server.properties.fullyQualifiedDomainName,
loginName: server.properties.administratorLogin
});
}
} }
});
const founds = svrIdRegExp.exec(svr.id);
const resouceGroup = founds[1];
const dbs = await sqlManagementClient.databases.listByServer(resouceGroup, svr.name);
dbs.forEach((db) => databases.push({
name: db.name,
serverName: svr.name,
serverFullName: svr.fullyQualifiedDomainName,
loginName: svr.administratorLogin
}));
}
return databases; return databases;
} }

View File

@@ -3,26 +3,33 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ServiceClientCredentials } from 'ms-rest';
import { SqlManagementClient } from 'azure-arm-sql';
import { azureResource } from '../../azure-resource'; import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces'; import { AzureResourceDatabaseServer } from '../../interfaces';
export class AzureResourceDatabaseServerService implements IAzureResourceService<AzureResourceDatabaseServer> {
public async getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise<AzureResourceDatabaseServer[]> {
const databaseServers: AzureResourceDatabaseServer[] = [];
const sqlManagementClient = new SqlManagementClient(credential, subscription.id); export interface DbServerGraphData extends GraphData {
const svrs = await sqlManagementClient.servers.list(); properties: {
fullyQualifiedDomainName: string;
administratorLogin: string;
};
}
svrs.forEach((svr) => databaseServers.push({ export const serversQuery = 'where type == "microsoft.sql/servers"';
name: svr.name,
fullName: svr.fullyQualifiedDomainName, export class AzureResourceDatabaseServerService extends ResourceServiceBase<DbServerGraphData, AzureResourceDatabaseServer> {
loginName: svr.administratorLogin,
protected get query(): string {
return serversQuery;
}
protected convertResource(resource: DbServerGraphData): AzureResourceDatabaseServer {
return {
id: resource.id,
name: resource.name,
fullName: resource.properties.fullyQualifiedDomainName,
loginName: resource.properties.administratorLogin,
defaultDatabaseName: 'master' defaultDatabaseName: 'master'
})); };
return databaseServers;
} }
} }

View File

@@ -30,7 +30,7 @@ export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDat
protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem { protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem {
return { return {
id: `databaseServer_${databaseServer.name}`, id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: databaseServer.name, label: databaseServer.name,
iconPath: { iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'), dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),

View File

@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext } from 'vscode';
import { ApiWrapper } from '../../../apiWrapper';
import { azureResource } from '../../azure-resource';
import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces';
import { PostgresServerTreeDataProvider as PostgresServerTreeDataProvider } from './postgresServerTreeDataProvider';
export class PostgresServerProvider implements azureResource.IAzureResourceProvider {
public constructor(
private _databaseServerService: IAzureResourceService<AzureResourceDatabaseServer>,
private _apiWrapper: ApiWrapper,
private _extensionContext: ExtensionContext
) {
}
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
return new PostgresServerTreeDataProvider(this._databaseServerService, this._apiWrapper, this._extensionContext);
}
public get providerId(): string {
return 'azure.resource.providers.postgresServer';
}
}

View File

@@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
import { AzureResourceDatabaseServer } from '../../interfaces';
export interface DbServerGraphData extends GraphData {
properties: {
fullyQualifiedDomainName: string;
administratorLogin: string;
};
}
export const serversQuery = 'where type == "microsoft.dbforpostgresql/servers"';
export class PostgresServerService extends ResourceServiceBase<DbServerGraphData, AzureResourceDatabaseServer> {
protected get query(): string {
return serversQuery;
}
protected convertResource(resource: DbServerGraphData): AzureResourceDatabaseServer {
return {
id: resource.id,
name: resource.name,
fullName: resource.properties.fullyQualifiedDomainName,
loginName: resource.properties.administratorLogin,
defaultDatabaseName: 'postgres'
};
}
}

View File

@@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionNodeType, TreeItem } from 'azdata';
import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceItemType } from '../../constants';
import { ApiWrapper } from '../../../apiWrapper';
import { generateGuid } from '../../utils';
import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { azureResource } from '../../azure-resource';
export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase<AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.postgresServerContainer';
private static readonly containerLabel = localize('azure.resource.providers.databaseServer.treeDataProvider.postgresServerContainerLabel', "Azure Database for PostgreSQL Servers");
public constructor(
databaseServerService: IAzureResourceService<AzureResourceDatabaseServer>,
apiWrapper: ApiWrapper,
private _extensionContext: ExtensionContext
) {
super(databaseServerService, apiWrapper);
}
protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem {
return {
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: databaseServer.name,
// TODO: should get PGSQL-specific icons (also needed in that extension)
iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),
light: this._extensionContext.asAbsolutePath('resources/light/sql_server.svg')
},
collapsibleState: TreeItemCollapsibleState.Collapsed,
contextValue: AzureResourceItemType.databaseServer,
payload: {
id: generateGuid(),
connectionName: undefined,
serverName: databaseServer.fullName,
databaseName: databaseServer.defaultDatabaseName,
userName: `${databaseServer.loginName}@${databaseServer.fullName}`,
password: '',
authenticationType: 'SqlLogin',
savePassword: true,
groupFullName: '',
groupId: '',
providerName: 'PGSQL',
saveProfile: false,
options: {
// Set default for SSL or will get error complaining about it not being set correctly
'sslmode': 'require'
}
},
childProvider: 'PGSQL',
type: ExtensionNodeType.Server
};
}
protected createContainerNode(): azureResource.IAzureResourceNode {
return {
account: undefined,
subscription: undefined,
tenantId: undefined,
treeItem: {
id: PostgresServerTreeDataProvider.containerId,
label: PostgresServerTreeDataProvider.containerLabel,
iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'),
light: this._extensionContext.asAbsolutePath('resources/light/folder.svg')
},
collapsibleState: TreeItemCollapsibleState.Collapsed,
contextValue: AzureResourceItemType.databaseServerContainer
}
};
}
}

View File

@@ -4,17 +4,19 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { AzureResource, TreeItem } from 'azdata'; import { AzureResource, TreeItem } from 'azdata';
import { TokenCredentials } from 'ms-rest'; import * as msRest from '@azure/ms-rest-js';
import { azureResource } from '../azure-resource'; import { azureResource } from '../azure-resource';
import { ApiWrapper } from '../../apiWrapper'; import { ApiWrapper } from '../../apiWrapper';
import { IAzureResourceService, AzureSqlResource } from '../interfaces'; import { IAzureResourceService, AzureSqlResource } from '../interfaces';
import { AzureResourceErrorMessageUtil } from '../utils';
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
export abstract class ResourceTreeDataProviderBase<T extends AzureSqlResource> implements azureResource.IAzureResourceTreeDataProvider { export abstract class ResourceTreeDataProviderBase<T extends AzureSqlResource> implements azureResource.IAzureResourceTreeDataProvider {
public constructor( public constructor(
protected _resourceService: IAzureResourceService<T>, protected _resourceService: IAzureResourceService<T>,
protected _apiWrapper: ApiWrapper, protected _apiWrapper: ApiWrapper
) { ) {
} }
@@ -23,24 +25,94 @@ export abstract class ResourceTreeDataProviderBase<T extends AzureSqlResource> i
} }
public async getChildren(element?: azureResource.IAzureResourceNode): Promise<azureResource.IAzureResourceNode[]> { public async getChildren(element?: azureResource.IAzureResourceNode): Promise<azureResource.IAzureResourceNode[]> {
if (!element) { try {
return [this.createContainerNode()]; if (!element) {
} return [this.createContainerNode()];
}
let resources: T[] = await this.getResources(element);
return resources.map((resource) => <azureResource.IAzureResourceNode>{
account: element.account,
subscription: element.subscription,
tenantId: element.tenantId,
treeItem: this.getTreeItemForResource(resource)
}).sort((a, b) => a.treeItem.label.localeCompare(b.treeItem.label));
} catch (error) {
console.log(AzureResourceErrorMessageUtil.getErrorMessage(error));
throw error;
}
}
private async getResources(element: azureResource.IAzureResourceNode): Promise<T[]> {
const tokens = await this._apiWrapper.getSecurityToken(element.account, AzureResource.ResourceManagement); const tokens = await this._apiWrapper.getSecurityToken(element.account, AzureResource.ResourceManagement);
const credential = new TokenCredentials(tokens[element.tenantId].token, tokens[element.tenantId].tokenType); const credential = new msRest.TokenCredentials(tokens[element.tenantId].token, tokens[element.tenantId].tokenType);
const resources: T[] = await this._resourceService.getResources(element.subscription, credential) || <T[]>[]; const resources: T[] = await this._resourceService.getResources(element.subscription, credential) || <T[]>[];
return resources;
return resources.map((resource) => <azureResource.IAzureResourceNode>{
account: element.account,
subscription: element.subscription,
tenantId: element.tenantId,
treeItem: this.getTreeItemForResource(resource)
}).sort((a, b) => a.treeItem.label.localeCompare(b.treeItem.label));
} }
protected abstract getTreeItemForResource(resource: T): TreeItem; protected abstract getTreeItemForResource(resource: T): TreeItem;
protected abstract createContainerNode(): azureResource.IAzureResourceNode; protected abstract createContainerNode(): azureResource.IAzureResourceNode;
} }
export interface GraphData {
id: string;
name: string;
location: string;
type: string;
resourceGroup: string;
}
export async function queryGraphResources<T extends GraphData>(resourceClient: ResourceGraphClient, subId: string, resourceQuery: string): Promise<T[]> {
const allResources: T[] = [];
let totalProcessed = 0;
let doQuery = async (skipToken?: string) => {
const response = await resourceClient.resources({
subscriptions: [subId],
query: resourceQuery,
options: {
resultFormat: 'objectArray',
skipToken: skipToken
}
});
const resources: T[] = response.data;
totalProcessed += resources.length;
allResources.push(...resources);
if (response.skipToken && totalProcessed < response.totalRecords) {
await doQuery(response.skipToken);
}
};
await doQuery();
return allResources;
}
export abstract class ResourceServiceBase<T extends GraphData, U extends AzureSqlResource> implements IAzureResourceService<U> {
constructor() {
}
protected abstract get query(): string;
public async getResources(subscription: azureResource.AzureResourceSubscription, credential: msRest.ServiceClientCredentials): Promise<U[]> {
const convertedResources: U[] = [];
const resourceClient = new ResourceGraphClient(credential);
let graphResources = await queryGraphResources<T>(resourceClient, subscription.id, this.query);
let ids = new Set<string>();
graphResources.forEach((res) => {
if (!ids.has(res.id)) {
ids.add(res.id);
let converted = this.convertResource(res);
convertedResources.push(converted);
}
});
return convertedResources;
}
protected abstract convertResource(resource: T): U;
}

View File

@@ -3,25 +3,31 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ServiceClientCredentials as OldSc } from 'ms-rest'; import { AzureResourceDatabaseServer } from '../../interfaces';
import { SqlManagementClient } from 'azure-arm-sql'; import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
import { azureResource } from '../../azure-resource'; export interface SqlInstanceGraphData extends GraphData {
import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces'; properties: {
fullyQualifiedDomainName: string;
administratorLogin: string;
};
}
export class SqlInstanceResourceService implements IAzureResourceService<AzureResourceDatabaseServer> { const instanceQuery = 'where type == "microsoft.sql/managedinstances"';
public async getResources(subscription: azureResource.AzureResourceSubscription, credential: OldSc): Promise<AzureResourceDatabaseServer[]> {
const databaseServers: AzureResourceDatabaseServer[] = [];
const sqlManagementClient = new SqlManagementClient(credential, subscription.id);
const svrs = await sqlManagementClient.managedInstances.list();
svrs.forEach((svr) => databaseServers.push({ export class SqlInstanceResourceService extends ResourceServiceBase<SqlInstanceGraphData, AzureResourceDatabaseServer> {
name: svr.name,
fullName: svr.fullyQualifiedDomainName, protected get query(): string {
loginName: svr.administratorLogin, return instanceQuery;
}
protected convertResource(resource: SqlInstanceGraphData): AzureResourceDatabaseServer {
return {
id: resource.id,
name: resource.name,
fullName: resource.properties.fullyQualifiedDomainName,
loginName: resource.properties.administratorLogin,
defaultDatabaseName: 'master' defaultDatabaseName: 'master'
})); };
return databaseServers;
} }
} }

View File

@@ -17,7 +17,7 @@ import { azureResource } from '../../azure-resource';
export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<AzureResourceDatabaseServer> { export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.sqlInstanceContainer'; private static readonly containerId = 'azure.resource.providers.sqlInstanceContainer';
private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "SQL Instances"); private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "SQL Managed Instances");
public constructor( public constructor(
databaseServerService: IAzureResourceService<AzureResourceDatabaseServer>, databaseServerService: IAzureResourceService<AzureResourceDatabaseServer>,
@@ -30,7 +30,7 @@ export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<Az
protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem { protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem {
return { return {
id: `sqlInstance_${databaseServer.name}`, id: `sqlInstance_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: databaseServer.name, label: databaseServer.name,
iconPath: { iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_instance_inverse.svg'), dark: this._extensionContext.asAbsolutePath('resources/dark/sql_instance_inverse.svg'),

View File

@@ -3,11 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict';
import { Account } from 'azdata'; import { Account } from 'azdata';
import { ServiceClientCredentials } from 'ms-rest'; import { ServiceClientCredentials } from '@azure/ms-rest-js';
import { SubscriptionClient } from 'azure-arm-resource'; import { SubscriptionClient } from '@azure/arm-subscriptions';
import { azureResource } from '../azure-resource'; import { azureResource } from '../azure-resource';
import { IAzureResourceSubscriptionService } from '../interfaces'; import { IAzureResourceSubscriptionService } from '../interfaces';
@@ -16,7 +14,7 @@ export class AzureResourceSubscriptionService implements IAzureResourceSubscript
public async getSubscriptions(account: Account, credential: ServiceClientCredentials): Promise<azureResource.AzureResourceSubscription[]> { public async getSubscriptions(account: Account, credential: ServiceClientCredentials): Promise<azureResource.AzureResourceSubscription[]> {
const subscriptions: azureResource.AzureResourceSubscription[] = []; const subscriptions: azureResource.AzureResourceSubscription[] = [];
const subClient = new SubscriptionClient.SubscriptionClient(credential); const subClient = new SubscriptionClient(credential);
const subs = await subClient.subscriptions.list(); const subs = await subClient.subscriptions.list();
subs.forEach((sub) => subscriptions.push({ subs.forEach((sub) => subscriptions.push({
id: sub.subscriptionId, id: sub.subscriptionId,

View File

@@ -5,11 +5,12 @@
import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Account, NodeInfo, AzureResource } from 'azdata'; import { Account, NodeInfo, AzureResource } from 'azdata';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from '@azure/ms-rest-js';
import { AppContext } from '../../appContext';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
import { AppContext } from '../../appContext';
import { azureResource } from '../azure-resource'; import { azureResource } from '../azure-resource';
import { TreeNode } from '../treeNode'; import { TreeNode } from '../treeNode';
import { AzureResourceCredentialError } from '../errors'; import { AzureResourceCredentialError } from '../errors';

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Account, NodeInfo } from 'azdata'; import { Account, NodeInfo } from 'azdata';
import { AppContext } from '../../appContext'; import { AppContext } from '../../appContext';

View File

@@ -29,6 +29,8 @@ import { registerAzureResourceCommands } from './azureResource/commands';
import { AzureResourceTreeProvider } from './azureResource/tree/treeProvider'; import { AzureResourceTreeProvider } from './azureResource/tree/treeProvider';
import { SqlInstanceResourceService } from './azureResource/providers/sqlinstance/sqlInstanceService'; import { SqlInstanceResourceService } from './azureResource/providers/sqlinstance/sqlInstanceService';
import { SqlInstanceProvider } from './azureResource/providers/sqlinstance/sqlInstanceProvider'; import { SqlInstanceProvider } from './azureResource/providers/sqlinstance/sqlInstanceProvider';
import { PostgresServerProvider } from './azureResource/providers/postgresServer/postgresServerProvider';
import { PostgresServerService } from './azureResource/providers/postgresServer/postgresServerService';
let extensionContext: vscode.ExtensionContext; let extensionContext: vscode.ExtensionContext;
@@ -65,7 +67,7 @@ export async function activate(context: vscode.ExtensionContext) {
} }
// Create the provider service and activate // Create the provider service and activate
initAzureAccountProvider(extensionContext, storagePath); initAzureAccountProvider(extensionContext, storagePath).catch((err) => console.log(err));
registerAzureServices(appContext); registerAzureServices(appContext);
const azureResourceTree = new AzureResourceTreeProvider(appContext); const azureResourceTree = new AzureResourceTreeProvider(appContext);
@@ -77,7 +79,8 @@ export async function activate(context: vscode.ExtensionContext) {
return [ return [
new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), apiWrapper, extensionContext), new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), apiWrapper, extensionContext),
new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), apiWrapper, extensionContext), new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), apiWrapper, extensionContext),
new SqlInstanceProvider(new SqlInstanceResourceService(), apiWrapper, extensionContext) new SqlInstanceProvider(new SqlInstanceResourceService(), apiWrapper, extensionContext),
new PostgresServerProvider(new PostgresServerService(), apiWrapper, extensionContext)
]; ];
} }
}; };

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict';
import * as should from 'should'; import * as should from 'should';
import * as TypeMoq from 'typemoq'; import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata'; import * as azdata from 'azdata';

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict';
import * as should from 'should'; import * as should from 'should';
import * as TypeMoq from 'typemoq'; import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata'; import * as azdata from 'azdata';

View File

@@ -8,7 +8,7 @@ import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import 'mocha'; import 'mocha';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from '@azure/ms-rest-js';
import { AppContext } from '../../../appContext'; import { AppContext } from '../../../appContext';
import { azureResource } from '../../../azureResource/azure-resource'; import { azureResource } from '../../../azureResource/azure-resource';

View File

@@ -2,6 +2,46 @@
# yarn lockfile v1 # yarn lockfile v1
"@azure/arm-resourcegraph@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@azure/arm-resourcegraph/-/arm-resourcegraph-2.0.0.tgz#f766e4a0b4285c114d25e98f22f8c260fe042469"
integrity sha512-6tWBlHlqlqUlNP0Ob+6x6uH37YICbgXg03UiVWr9Yno060KJ/0BPwlSfTgjvLkBiyXnutPb6HpH5/+GMUICzYQ==
dependencies:
"@azure/ms-rest-azure-js" "^1.3.2"
"@azure/ms-rest-js" "^1.8.1"
tslib "^1.9.3"
"@azure/arm-subscriptions@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@azure/arm-subscriptions/-/arm-subscriptions-1.0.0.tgz#ab65a5cd4d8b8c878ff6621428f29137b84eb1d6"
integrity sha512-DoZFcF+ePkGhrxQ4X/LxBoWipqpkZIt9g+itXJ4HaQNExn0hNO27Cs6kNZYpIdCs5Zu+2DbjRs2i8OqG3QbE9w==
dependencies:
"@azure/ms-rest-azure-js" "^1.1.0"
"@azure/ms-rest-js" "^1.1.0"
tslib "^1.9.3"
"@azure/ms-rest-azure-js@^1.1.0", "@azure/ms-rest-azure-js@^1.3.2":
version "1.3.8"
resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-js/-/ms-rest-azure-js-1.3.8.tgz#96b518223d3baa2496b2981bc07288b3d887486e"
integrity sha512-AHLfDTCyIH6wBK6+CpImI6sc9mLZ17ZgUrTx3Rhwv+3Mb3Z73BxormkarfR6Stb6scrBYitxJ27FXyndXlGAYg==
dependencies:
"@azure/ms-rest-js" "^1.8.10"
tslib "^1.9.3"
"@azure/ms-rest-js@^1.1.0", "@azure/ms-rest-js@^1.8.1", "@azure/ms-rest-js@^1.8.10":
version "1.8.13"
resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-1.8.13.tgz#ed0cd86469697378cd39d79d5589e877a3bc87a6"
integrity sha512-jAa6Y2XrvwbEqkaEXDHK+ReNo0WnCPS+LgQ1dRAJUUNxK4CghF5u+SXsVtPENritilVE7FVteqsLOtlhTk+haA==
dependencies:
"@types/tunnel" "0.0.0"
axios "^0.19.0"
form-data "^2.3.2"
tough-cookie "^2.4.3"
tslib "^1.9.2"
tunnel "0.0.6"
uuid "^3.2.1"
xml2js "^0.4.19"
"@types/caseless@*": "@types/caseless@*":
version "0.12.2" version "0.12.2"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
@@ -44,6 +84,13 @@
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d"
integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg== integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==
"@types/tunnel@0.0.0":
version "0.0.0"
resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.0.tgz#c2a42943ee63c90652a5557b8c4e56cda77f944e"
integrity sha512-FGDp0iBRiBdPjOgjJmn1NH0KDLN+Z8fRmo+9J7XGBhubq1DPrGrbmG4UTlGzrpbCpesMqD0sWkzi27EYkOMHyg==
dependencies:
"@types/node" "*"
adal-node@^0.1.28: adal-node@^0.1.28:
version "0.1.28" version "0.1.28"
resolved "https://registry.yarnpkg.com/adal-node/-/adal-node-0.1.28.tgz#468c4bb3ebbd96b1270669f4b9cba4e0065ea485" resolved "https://registry.yarnpkg.com/adal-node/-/adal-node-0.1.28.tgz#468c4bb3ebbd96b1270669f4b9cba4e0065ea485"
@@ -157,13 +204,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
async@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
integrity sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==
dependencies:
lodash "^4.14.0"
async@>=0.6.0: async@>=0.6.0:
version "2.6.1" version "2.6.1"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
@@ -186,21 +226,13 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
azure-arm-resource@^7.0.0: axios@^0.19.0:
version "7.3.0" version "0.19.0"
resolved "https://registry.yarnpkg.com/azure-arm-resource/-/azure-arm-resource-7.3.0.tgz#b45c4b4ab48719c00b9a2554cce6c2cb014a6d6f" resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
integrity sha512-2K+ps1Iwa4PBQFwdCn1X8kAVIRLH5M7nlNZtfOWaYd7DXJ131qJpwW8ul6gKZgG7DAI3PBodrGsHFvPdgA+AzQ== integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
dependencies: dependencies:
ms-rest "^2.3.3" follow-redirects "1.5.10"
ms-rest-azure "^2.5.5" is-buffer "^2.0.2"
azure-arm-sql@^5.0.1:
version "5.6.0"
resolved "https://registry.yarnpkg.com/azure-arm-sql/-/azure-arm-sql-5.6.0.tgz#9a2a88c70ef1924ee8f7f351ec7eaf28482a6dae"
integrity sha512-j1T2Cdbs/fV55a4Rz72KdtxIwyCt7BXPIjHnv5q1j2tbvCofd5v6hRqYbyLlIhtdxY4ygrPet8UmfTgUt4RA6w==
dependencies:
ms-rest "^2.3.3"
ms-rest-azure "^2.5.5"
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.0" version "1.0.0"
@@ -364,7 +396,7 @@ date-utils@*:
resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64"
integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q= integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q=
debug@3.1.0: debug@3.1.0, debug@=3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
@@ -392,7 +424,7 @@ deep-assign@^1.0.0:
dependencies: dependencies:
is-obj "^1.0.0" is-obj "^1.0.0"
define-properties@^1.1.2: define-properties@^1.1.2, define-properties@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
@@ -451,6 +483,31 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
es-abstract@^1.5.1:
version "1.16.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d"
integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==
dependencies:
es-to-primitive "^1.2.0"
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.0"
is-callable "^1.1.4"
is-regex "^1.0.4"
object-inspect "^1.6.0"
object-keys "^1.1.1"
string.prototype.trimleft "^2.1.0"
string.prototype.trimright "^2.1.0"
es-to-primitive@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
dependencies:
is-callable "^1.1.4"
is-date-object "^1.0.1"
is-symbol "^1.0.2"
escape-string-regexp@1.0.5: escape-string-regexp@1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
@@ -529,11 +586,27 @@ flush-write-stream@^1.0.2:
inherits "^2.0.3" inherits "^2.0.3"
readable-stream "^2.3.6" readable-stream "^2.3.6"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
forever-agent@~0.6.1: forever-agent@~0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@^2.3.2:
version "2.5.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
form-data@~2.3.2: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -735,7 +808,7 @@ has-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
has@^1.0.3: has@^1.0.1, has@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
@@ -777,11 +850,26 @@ is-absolute@^1.0.0:
is-relative "^1.0.0" is-relative "^1.0.0"
is-windows "^1.0.1" is-windows "^1.0.1"
is-buffer@^1.1.5, is-buffer@^1.1.6, is-buffer@~1.1.1: is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-buffer@^2.0.2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
is-extglob@^2.1.0: is-extglob@^2.1.0:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@@ -804,6 +892,13 @@ is-obj@^1.0.0:
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
dependencies:
has "^1.0.1"
is-relative@^1.0.0: is-relative@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
@@ -811,10 +906,12 @@ is-relative@^1.0.0:
dependencies: dependencies:
is-unc-path "^1.0.0" is-unc-path "^1.0.0"
is-stream@^1.1.0: is-symbol@^1.0.2:
version "1.1.0" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
dependencies:
has-symbols "^1.0.0"
is-typedarray@~1.0.0: is-typedarray@~1.0.0:
version "1.0.0" version "1.0.0"
@@ -934,16 +1031,16 @@ lead@^1.0.0:
dependencies: dependencies:
flush-write-stream "^1.0.2" flush-write-stream "^1.0.2"
lodash@^4.14.0, lodash@^4.17.10, lodash@^4.17.4:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
lodash@^4.16.4: lodash@^4.16.4:
version "4.17.15" version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
lodash@^4.17.10, lodash@^4.17.4:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
map-stream@0.0.7: map-stream@0.0.7:
version "0.0.7" version "0.0.7"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8"
@@ -1046,37 +1143,6 @@ mocha@^5.2.0:
mkdirp "0.5.1" mkdirp "0.5.1"
supports-color "5.4.0" supports-color "5.4.0"
moment@^2.21.0, moment@^2.22.2:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
ms-rest-azure@^2.5.5:
version "2.6.0"
resolved "https://registry.yarnpkg.com/ms-rest-azure/-/ms-rest-azure-2.6.0.tgz#2098efec529eecfa0c6e215b69143abcaba12140"
integrity sha512-J6386a9krZ4VtU7CRt+Ypgo9RGf8+d3gjMBkH7zbkM4zzkhbbMOYiPRaZ+bHZcfihkKLlktTgA6rjshTjF329A==
dependencies:
adal-node "^0.1.28"
async "2.6.0"
moment "^2.22.2"
ms-rest "^2.3.2"
request "^2.88.0"
uuid "^3.2.1"
ms-rest@^2.3.2, ms-rest@^2.3.3, ms-rest@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/ms-rest/-/ms-rest-2.5.0.tgz#d483c003f7de7703ade6bc19c3b4319affac2687"
integrity sha512-QUTg9CsmWpofDO0MR37z8B28/T9ObpQ+FM23GGDMKXw8KYDJ3cEBdK6dJTDDrtSoZG3U+S/vdmSEwJ7FNj6Kog==
dependencies:
duplexer "^0.1.1"
is-buffer "^1.1.6"
is-stream "^1.1.0"
moment "^2.21.0"
request "^2.88.0"
through "^2.3.8"
tunnel "0.0.5"
uuid "^3.2.1"
ms@2.0.0: ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -1124,7 +1190,12 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
object-keys@^1.0.11, object-keys@^1.0.12: object-inspect@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@@ -1139,6 +1210,14 @@ object.assign@^4.0.4:
has-symbols "^1.0.0" has-symbols "^1.0.0"
object-keys "^1.0.11" object-keys "^1.0.11"
object.getownpropertydescriptors@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=
dependencies:
define-properties "^1.1.2"
es-abstract "^1.5.1"
once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -1206,6 +1285,11 @@ psl@^1.1.24:
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184"
integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==
psl@^1.1.28:
version "1.4.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2"
integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==
pump@^2.0.0: pump@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
@@ -1228,7 +1312,7 @@ punycode@^1.4.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0: punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
@@ -1360,6 +1444,11 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
semver@^5.4.1: semver@^5.4.1:
version "5.7.0" version "5.7.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
@@ -1488,6 +1577,22 @@ streamifier@~0.1.1:
resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f"
integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=
string.prototype.trimleft@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634"
integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==
dependencies:
define-properties "^1.1.3"
function-bind "^1.1.1"
string.prototype.trimright@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58"
integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==
dependencies:
define-properties "^1.1.3"
function-bind "^1.1.1"
string_decoder@~0.10.x: string_decoder@~0.10.x:
version "0.10.31" version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
@@ -1574,6 +1679,14 @@ to-through@^2.0.0:
dependencies: dependencies:
through2 "^2.0.3" through2 "^2.0.3"
tough-cookie@^2.4.3:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
tough-cookie@~2.4.3: tough-cookie@~2.4.3:
version "2.4.3" version "2.4.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
@@ -1582,6 +1695,11 @@ tough-cookie@~2.4.3:
psl "^1.1.24" psl "^1.1.24"
punycode "^1.4.1" punycode "^1.4.1"
tslib@^1.9.2, tslib@^1.9.3:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
tunnel-agent@^0.6.0: tunnel-agent@^0.6.0:
version "0.6.0" version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
@@ -1589,10 +1707,10 @@ tunnel-agent@^0.6.0:
dependencies: dependencies:
safe-buffer "^5.0.1" safe-buffer "^5.0.1"
tunnel@0.0.5: tunnel@0.0.6:
version "0.0.5" version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.5.tgz#d1532254749ed36620fcd1010865495a1fa9d0ae" resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-gj5sdqherx4VZKMcBA4vewER7zdK25Td+z1npBqpbDys4eJrLx+SlYjJvq1bDXs2irkuJM5pf8ktaEQVipkrbA== integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
tweetnacl@^0.14.3, tweetnacl@~0.14.0: tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5" version "0.14.5"
@@ -1646,6 +1764,14 @@ util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
util.promisify@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
dependencies:
define-properties "^1.1.2"
object.getownpropertydescriptors "^2.0.3"
uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2: uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
@@ -1768,11 +1894,25 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xml2js@^0.4.19:
version "0.4.22"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02"
integrity sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==
dependencies:
sax ">=0.6.0"
util.promisify "~1.0.0"
xmlbuilder "~11.0.0"
xml@^1.0.0: xml@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=
xmlbuilder@~11.0.0:
version "11.0.1"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
"xmldom@>= 0.1.x": "xmldom@>= 0.1.x":
version "0.1.27" version "0.1.27"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"