diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js
index e3021c33d8..fa024420b0 100644
--- a/build/gulpfile.hygiene.js
+++ b/build/gulpfile.hygiene.js
@@ -104,6 +104,9 @@ const indentationFilter = [
'!extensions/resource-deployment/notebooks/**',
'!extensions/mssql/notebooks/**',
'!extensions/integration-tests/testData/**',
+ '!extensions/sql-database-projects/resources/templates/*.xml',
+ '!extensions/sql-database-projects/src/test/baselines/*.xml',
+ '!extensions/sql-database-projects/src/test/baselines/*.json',
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
'!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts',
'!resources/linux/snap/electron-launch'
diff --git a/extensions/sql-database-projects/coverConfig.json b/extensions/sql-database-projects/coverConfig.json
new file mode 100644
index 0000000000..9d13013c7a
--- /dev/null
+++ b/extensions/sql-database-projects/coverConfig.json
@@ -0,0 +1,19 @@
+{
+ "enabled": true,
+ "relativeSourcePath": "..",
+ "relativeCoverageDir": "../../coverage",
+ "ignorePatterns": [
+ "**/node_modules/**",
+ "**/test/**"
+ ],
+ "includePid": false,
+ "reports": [
+ "cobertura",
+ "lcov"
+ ],
+ "verbose": false,
+ "remapOptions": {
+ "basePath": "..",
+ "useAbsolutePaths": true
+ }
+}
diff --git a/extensions/sql-database-projects/package.json b/extensions/sql-database-projects/package.json
index dc5b30964e..961d3264f1 100644
--- a/extensions/sql-database-projects/package.json
+++ b/extensions/sql-database-projects/package.json
@@ -36,6 +36,41 @@
"command": "sqlDatabaseProjects.open",
"title": "%sqlDatabaseProjects.open%",
"category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.close",
+ "title": "%sqlDatabaseProjects.close%",
+ "category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.newScript",
+ "title": "%sqlDatabaseProjects.newScript%",
+ "category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.newTable",
+ "title": "%sqlDatabaseProjects.newTable%",
+ "category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.newView",
+ "title": "%sqlDatabaseProjects.newView%",
+ "category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.newStoredProcedure",
+ "title": "%sqlDatabaseProjects.newStoredProcedure%",
+ "category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.newItem",
+ "title": "%sqlDatabaseProjects.newItem%",
+ "category": "%sqlDatabaseProjects.displayName%"
+ },
+ {
+ "command": "sqlDatabaseProjects.newFolder",
+ "title": "%sqlDatabaseProjects.newFolder%",
+ "category": "%sqlDatabaseProjects.displayName%"
}
],
"menus": {
@@ -45,6 +80,64 @@
},
{
"command": "sqlDatabaseProjects.open"
+ },
+ {
+ "command": "sqlDatabaseProjects.close",
+ "when": "false"
+ },
+ {
+ "command": "sqlDatabaseProjects.newScript",
+ "when": "false"
+ },
+ {
+ "command": "sqlDatabaseProjects.newTable",
+ "when": "false"
+ },
+ {
+ "command": "sqlDatabaseProjects.newView",
+ "when": "false"
+ },
+ {
+ "command": "sqlDatabaseProjects.newStoredProcedure",
+ "when": "false"
+ },
+ {
+ "command": "sqlDatabaseProjects.newItem",
+ "when": "false"
+ },
+ {
+ "command": "sqlDatabaseProjects.newFolder",
+ "when": "false"
+ }
+ ],
+ "view/item/context": [
+ {
+ "command": "sqlDatabaseProjects.close",
+ "when": "view == sqlDatabaseProjectsView"
+ },
+ {
+ "command": "sqlDatabaseProjects.newScript",
+ "when": "view == sqlDatabaseProjectsView"
+ },
+ {
+ "command": "sqlDatabaseProjects.newTable",
+ "when": "view == sqlDatabaseProjectsView"
+ },
+ {
+ "command": "sqlDatabaseProjects.newView",
+ "when": "view == sqlDatabaseProjectsView"
+ },
+ {
+ "command": "sqlDatabaseProjects.newStoredProcedure",
+ "when": "view == sqlDatabaseProjectsView"
+ },
+ {
+ "command": "sqlDatabaseProjects.newItem",
+ "when": "view == sqlDatabaseProjectsView"
+ },
+ {
+ "command": "sqlDatabaseProjects.newFolder",
+ "when": "view == sqlDatabaseProjectsView"
}
]
},
@@ -59,12 +152,18 @@
}
},
"dependencies": {
+ "vscode-languageclient": "^5.3.0-next.1",
"vscode-nls": "^3.2.1",
- "xml2js": "^0.4.23"
+ "xmldom": "^0.3.0"
},
"devDependencies": {
- "@types/xml2js": "^0.4.5",
+ "@types/xmldom": "^0.1.29",
+ "mocha-junit-reporter": "^1.17.0",
+ "mocha-multi-reporters": "^1.1.7",
+ "should": "^13.2.1",
"tslint": "^5.8.0",
- "typescript": "^2.6.1"
+ "typemoq": "^2.1.0",
+ "typescript": "^2.6.1",
+ "vscodetestcover": "github:corivera/vscodetestcover#1.0.6"
}
}
diff --git a/extensions/sql-database-projects/package.nls.json b/extensions/sql-database-projects/package.nls.json
index b9ebb7ff74..e681585477 100644
--- a/extensions/sql-database-projects/package.nls.json
+++ b/extensions/sql-database-projects/package.nls.json
@@ -1,7 +1,16 @@
{
+ "title.projectsView": "Projects",
+
"sqlDatabaseProjects.displayName": "Database Projects",
"sqlDatabaseProjects.description": "Design and deploy SQL database schemas",
"sqlDatabaseProjects.new": "New Database Project",
"sqlDatabaseProjects.open": "Open Database Project",
- "title.projectsView": "Projects"
+ "sqlDatabaseProjects.close": "Close Database Project",
+
+ "sqlDatabaseProjects.newScript": "Add Script",
+ "sqlDatabaseProjects.newTable": "Add Table",
+ "sqlDatabaseProjects.newView": "Add View",
+ "sqlDatabaseProjects.newStoredProcedure": "Add Stored Procedure",
+ "sqlDatabaseProjects.newItem": "Add Item...",
+ "sqlDatabaseProjects.newFolder": "Add Folder"
}
diff --git a/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml b/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml
new file mode 100644
index 0000000000..9095afb3a4
--- /dev/null
+++ b/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml
@@ -0,0 +1,60 @@
+
+
+
+ Debug
+ AnyCPU
+ @@PROJECT_NAME@@
+ 2.0
+ 4.1
+ {@@PROJECT_GUID@@}
+ Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider
+ Database
+
+
+ @@PROJECT_NAME@@
+ @@PROJECT_NAME@@
+ 1033, CI
+ BySchemaAndSchemaType
+ True
+ v4.5
+ CS
+ Properties
+ False
+ True
+ True
+
+
+ bin\Release\
+ $(MSBuildProjectName).sql
+ False
+ pdbonly
+ true
+ false
+ true
+ prompt
+ 4
+
+
+ bin\Debug\
+ $(MSBuildProjectName).sql
+ false
+ true
+ full
+ false
+ true
+ true
+ prompt
+ 4
+
+
+ 11.0
+
+ True
+ 11.0
+
+
+
+
+
+
+
diff --git a/extensions/sql-database-projects/resources/templates/newTsqlScriptTemplate.sql b/extensions/sql-database-projects/resources/templates/newTsqlScriptTemplate.sql
new file mode 100644
index 0000000000..1b1d45125f
--- /dev/null
+++ b/extensions/sql-database-projects/resources/templates/newTsqlScriptTemplate.sql
@@ -0,0 +1 @@
+-- Write your own SQL object definition here, and it'll be included in your package.
diff --git a/extensions/sql-database-projects/resources/templates/newTsqlStoredProcedureTemplate.sql b/extensions/sql-database-projects/resources/templates/newTsqlStoredProcedureTemplate.sql
new file mode 100644
index 0000000000..168bf602ec
--- /dev/null
+++ b/extensions/sql-database-projects/resources/templates/newTsqlStoredProcedureTemplate.sql
@@ -0,0 +1,6 @@
+CREATE PROCEDURE [dbo].[@@OBJECT_NAME@@]
+ @param1 int = 0,
+ @param2 int
+AS
+ SELECT @param1, @param2
+RETURN 0
diff --git a/extensions/sql-database-projects/resources/templates/newTsqlTableTemplate.sql b/extensions/sql-database-projects/resources/templates/newTsqlTableTemplate.sql
new file mode 100644
index 0000000000..d8fe93cb30
--- /dev/null
+++ b/extensions/sql-database-projects/resources/templates/newTsqlTableTemplate.sql
@@ -0,0 +1,4 @@
+CREATE TABLE [dbo].[@@OBJECT_NAME@@]
+(
+ [Id] INT NOT NULL PRIMARY KEY
+)
diff --git a/extensions/sql-database-projects/resources/templates/newTsqlViewTemplate.sql b/extensions/sql-database-projects/resources/templates/newTsqlViewTemplate.sql
new file mode 100644
index 0000000000..17df2872d3
--- /dev/null
+++ b/extensions/sql-database-projects/resources/templates/newTsqlViewTemplate.sql
@@ -0,0 +1,2 @@
+CREATE VIEW [dbo].[@@OBJECT_NAME@@]
+ AS SELECT * FROM [SomeTableOrView]
diff --git a/extensions/sql-database-projects/src/common/constants.ts b/extensions/sql-database-projects/src/common/constants.ts
index 08e2da0e3f..40249dda9f 100644
--- a/extensions/sql-database-projects/src/common/constants.ts
+++ b/extensions/sql-database-projects/src/common/constants.ts
@@ -9,6 +9,7 @@ const localize = nls.loadMessageBundle();
// Placeholder values
export const dataSourcesFileName = 'datasources.json';
+export const sqlprojExtension = '.sqlproj';
// UI Strings
@@ -16,6 +17,9 @@ export const noOpenProjectMessage = localize('noProjectOpenMessage', "No open da
export const projectNodeName = localize('projectNodeName', "Database Project");
export const dataSourcesNodeName = localize('dataSourcesNodeName', "Data Sources");
export const sqlConnectionStringFriendly = localize('sqlConnectionStringFriendly', "SQL connection string");
+export const newDatabaseProjectName = localize('newDatabaseProjectName', "New database project name:");
+export const sqlDatabaseProject = localize('sqlDatabaseProject', "SQL database project");
+export function newObjectNamePrompt(objectType: string) { return localize('newObjectNamePrompt', 'New {0} name:', objectType); }
// Error messages
@@ -26,3 +30,21 @@ export const missingVersion = localize('missingVersion', "Missing 'version' entr
export const unrecognizedDataSourcesVersion = localize('unrecognizedDataSourcesVersion', "Unrecognized version: ");
export const unknownDataSourceType = localize('unknownDataSourceType', "Unknown data source type: ");
export const invalidSqlConnectionString = localize('invalidSqlConnectionString', "Invalid SQL connection string");
+export const projectNameRequired = localize('projectNameRequired', "Name is required to create a new database project.");
+export const projectLocationRequired = localize('projectLocationRequired', "Location is required to create a new database project.");
+export function projectAlreadyOpened(path: string) { return localize('projectAlreadyOpened', "Project '{0}' is already opened.", path); }
+export function projectAlreadyExists(name: string, path: string) { return localize('projectAlreadyExists', "A project named {0} already exists in {1}.", name, path); }
+
+
+// Project script types
+
+export const scriptFriendlyName = localize('scriptFriendlyName', "Script");
+export const tableFriendlyName = localize('tableFriendlyName', "Table");
+export const viewFriendlyName = localize('viewFriendlyName', "View");
+export const storedProcedureFriendlyName = localize('storedProcedureFriendlyName', "Stored Procedure");
+
+// SqlProj file XML names
+export const ItemGroup = 'ItemGroup';
+export const Build = 'Build';
+export const Folder = 'Folder';
+export const Include = 'Include';
diff --git a/extensions/sql-database-projects/src/controllers/databaseProjectTreeViewProvider.ts b/extensions/sql-database-projects/src/controllers/databaseProjectTreeViewProvider.ts
index fc9b728f3f..354a2a9052 100644
--- a/extensions/sql-database-projects/src/controllers/databaseProjectTreeViewProvider.ts
+++ b/extensions/sql-database-projects/src/controllers/databaseProjectTreeViewProvider.ts
@@ -6,7 +6,7 @@
import * as vscode from 'vscode';
import * as constants from '../common/constants';
-import { BaseProjectTreeItem, MessageTreeItem } from '../models/tree/baseTreeItem';
+import { BaseProjectTreeItem, MessageTreeItem, SpacerTreeItem } from '../models/tree/baseTreeItem';
import { ProjectRootTreeItem } from '../models/tree/projectTreeItem';
import { Project } from '../models/project';
@@ -39,16 +39,20 @@ export class SqlDatabaseProjectTreeViewProvider implements vscode.TreeDataProvid
return element.children;
}
+ /**
+ * Constructs a new set of root nodes from a list of Projects
+ * @param projects List of Projects
+ */
public load(projects: Project[]) {
- if (projects.length === 0) {
- vscode.window.showErrorMessage(constants.noSqlProjFiles);
- return;
- }
-
let newRoots: BaseProjectTreeItem[] = [];
for (const proj of projects) {
newRoots.push(new ProjectRootTreeItem(proj));
+ newRoots.push(SpacerTreeItem);
+ }
+
+ if (newRoots[newRoots.length - 1] === SpacerTreeItem) {
+ newRoots.pop(); // get rid of the trailing SpacerTreeItem
}
this.roots = newRoots;
diff --git a/extensions/sql-database-projects/src/controllers/mainController.ts b/extensions/sql-database-projects/src/controllers/mainController.ts
index 1a3b1cd50e..b34355e8cc 100644
--- a/extensions/sql-database-projects/src/controllers/mainController.ts
+++ b/extensions/sql-database-projects/src/controllers/mainController.ts
@@ -4,16 +4,18 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
-import * as nls from 'vscode-nls';
+import * as templateMap from '../templates/templateMap';
+import * as templates from '../templates/templates';
+import * as constants from '../common/constants';
+import * as path from 'path';
import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider';
import { getErrorMessage } from '../common/utils';
import { ProjectsController } from './projectController';
+import { BaseProjectTreeItem } from '../models/tree/baseTreeItem';
const SQL_DATABASE_PROJECTS_VIEW_ID = 'sqlDatabaseProjectsView';
-const localize = nls.loadMessageBundle();
-
/**
* The main controller class that initializes the extension
*/
@@ -40,11 +42,21 @@ export default class MainController implements vscode.Disposable {
private async initializeDatabaseProjects(): Promise {
// init commands
- vscode.commands.registerCommand('sqlDatabaseProjects.new', () => { console.log('"New Database Project" called.'); });
- vscode.commands.registerCommand('sqlDatabaseProjects.open', async () => { this.openProjectFromFile(); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.new', async () => { await this.createNewProject(); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.open', async () => { await this.openProjectFromFile(); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.close', (node: BaseProjectTreeItem) => { this.projectsController.closeProject(node); });
+
+ vscode.commands.registerCommand('sqlDatabaseProjects.newScript', async (node: BaseProjectTreeItem) => { await this.projectsController.addItemPrompt(node, templateMap.script); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.newTable', async (node: BaseProjectTreeItem) => { await this.projectsController.addItemPrompt(node, templateMap.table); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.newView', async (node: BaseProjectTreeItem) => { await this.projectsController.addItemPrompt(node, templateMap.view); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.newStoredProcedure', async (node: BaseProjectTreeItem) => { await this.projectsController.addItemPrompt(node, templateMap.storedProcedure); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.newItem', async (node: BaseProjectTreeItem) => { await this.projectsController.addItemPrompt(node); });
+ vscode.commands.registerCommand('sqlDatabaseProjects.newFolder', async (node: BaseProjectTreeItem) => { await this.projectsController.addFolderPrompt(node); });
// init view
this.extensionContext.subscriptions.push(vscode.window.registerTreeDataProvider(SQL_DATABASE_PROJECTS_VIEW_ID, this.dbProjectTreeViewProvider));
+
+ await templates.loadTemplates(path.join(this._context.extensionPath, 'resources', 'templates'));
}
/**
@@ -55,7 +67,7 @@ export default class MainController implements vscode.Disposable {
try {
let filter: { [key: string]: string[] } = {};
- filter[localize('sqlDatabaseProject', "SQL database project")] = ['sqlproj'];
+ filter[constants.sqlDatabaseProject] = ['sqlproj'];
let files: vscode.Uri[] | undefined = await vscode.window.showOpenDialog({ filters: filter });
@@ -70,6 +82,47 @@ export default class MainController implements vscode.Disposable {
}
}
+ /**
+ * Creates a new SQL database project from a template, prompting the user for a name and location
+ */
+ public async createNewProject(): Promise {
+ try {
+ let newProjName = await vscode.window.showInputBox({
+ prompt: constants.newDatabaseProjectName,
+ value: `DatabaseProject${this.projectsController.projects.length + 1}`
+ // TODO: Smarter way to suggest a name. Easy if we prompt for location first, but that feels odd...
+ });
+
+ if (!newProjName) {
+ // TODO: is this case considered an intentional cancellation (shouldn't warn) or an error case (should warn)?
+ vscode.window.showErrorMessage(constants.projectNameRequired);
+ return;
+ }
+
+ let selectionResult = await vscode.window.showOpenDialog({
+ canSelectFiles: false,
+ canSelectFolders: true,
+ canSelectMany: false,
+ defaultUri: vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri : undefined
+ });
+
+ if (!selectionResult) {
+ vscode.window.showErrorMessage(constants.projectLocationRequired);
+ return;
+ }
+
+ // TODO: what if the selected folder is outside the workspace?
+
+ const newProjFolderUri = (selectionResult as vscode.Uri[])[0];
+ console.log(newProjFolderUri.fsPath);
+ const newProjFilePath = await this.projectsController.createNewProject(newProjName as string, newProjFolderUri as vscode.Uri);
+ await this.projectsController.openProject(vscode.Uri.file(newProjFilePath));
+ }
+ catch (err) {
+ vscode.window.showErrorMessage(getErrorMessage(err));
+ }
+ }
+
public dispose(): void {
this.deactivate();
}
diff --git a/extensions/sql-database-projects/src/controllers/projectController.ts b/extensions/sql-database-projects/src/controllers/projectController.ts
index afab57015e..271d0d55e6 100644
--- a/extensions/sql-database-projects/src/controllers/projectController.ts
+++ b/extensions/sql-database-projects/src/controllers/projectController.ts
@@ -4,11 +4,20 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
-import { Project } from '../models/project';
-import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider';
import * as path from 'path';
import * as constants from '../common/constants';
import * as dataSources from '../models/dataSources/dataSources';
+import * as templateMap from '../templates/templateMap';
+import * as utils from '../common/utils';
+import * as UUID from 'vscode-languageclient/lib/utils/uuid';
+import * as templates from '../templates/templates';
+
+import { Project } from '../models/project';
+import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider';
+import { promises as fs } from 'fs';
+import { BaseProjectTreeItem } from '../models/tree/baseTreeItem';
+import { ProjectRootTreeItem } from '../models/tree/projectTreeItem';
+import { FolderNode } from '../models/tree/fileFolderTreeItem';
/**
* Controller for managing project lifecycle
@@ -22,8 +31,18 @@ export class ProjectsController {
this.projectTreeViewProvider = projTreeViewProvider;
}
- public async openProject(projectFile: vscode.Uri) {
- console.log('Loading project: ' + projectFile.fsPath);
+
+ public refreshProjectsTree() {
+ this.projectTreeViewProvider.load(this.projects);
+ }
+
+ public async openProject(projectFile: vscode.Uri): Promise {
+ for (const proj of this.projects) {
+ if (proj.projectFilePath === projectFile.fsPath) {
+ vscode.window.showInformationMessage(constants.projectAlreadyOpened(projectFile.fsPath));
+ return proj;
+ }
+ }
// Read project file
const newProject = new Project(projectFile.fsPath);
@@ -32,12 +51,173 @@ export class ProjectsController {
// Read datasources.json (if present)
const dataSourcesFilePath = path.join(path.dirname(projectFile.fsPath), constants.dataSourcesFileName);
- newProject.dataSources = await dataSources.load(dataSourcesFilePath);
+
+ try {
+ newProject.dataSources = await dataSources.load(dataSourcesFilePath);
+ }
+ catch (err) {
+ if (err instanceof dataSources.NoDataSourcesFileError) {
+ // TODO: prompt to create new datasources.json; for now, swallow
+ console.log(`No ${constants.dataSourcesFileName} file found.`);
+ }
+ else {
+ throw err;
+ }
+ }
+
+ this.refreshProjectsTree();
+
+ return newProject;
+ }
+
+ public async createNewProject(newProjName: string, folderUri: vscode.Uri, projectGuid?: string): Promise {
+ if (projectGuid && !UUID.isUUID(projectGuid)) {
+ throw new Error(`Specified GUID is invalid: '${projectGuid}'`);
+ }
+
+ const macroDict: Record = {
+ 'PROJECT_NAME': newProjName,
+ 'PROJECT_GUID': projectGuid ?? UUID.generateUuid().toUpperCase()
+ };
+
+ let newProjFileContents = this.macroExpansion(templates.newSqlProjectTemplate, macroDict);
+
+ let newProjFileName = newProjName;
+
+ if (!newProjFileName.toLowerCase().endsWith(constants.sqlprojExtension)) {
+ newProjFileName += constants.sqlprojExtension;
+ }
+
+ const newProjFilePath = path.join(folderUri.fsPath, newProjFileName);
+
+ let fileExists = false;
+ try {
+ await fs.access(newProjFilePath);
+ fileExists = true;
+ }
+ catch { } // file doesn't already exist
+
+ if (fileExists) {
+ throw new Error(constants.projectAlreadyExists(newProjFileName, folderUri.fsPath));
+ }
+
+ await fs.mkdir(path.dirname(newProjFilePath), { recursive: true });
+ await fs.writeFile(newProjFilePath, newProjFileContents);
+
+ return newProjFilePath;
+ }
+
+ public closeProject(treeNode: BaseProjectTreeItem) {
+ const project = this.getProjectContextFromTreeNode(treeNode);
+ this.projects = this.projects.filter((e) => { return e !== project; });
+ this.refreshProjectsTree();
+ }
+
+ public async addFolderPrompt(treeNode: BaseProjectTreeItem) {
+ const project = this.getProjectContextFromTreeNode(treeNode);
+ const newFolderName = await this.promptForNewObjectName(new templateMap.ProjectScriptType(templateMap.folder, 'Folder', ''), project);
+
+ if (!newFolderName) {
+ return; // user cancelled
+ }
+
+ const relativeFolderPath = this.prependContextPath(treeNode, newFolderName);
+
+ await project.addFolderItem(relativeFolderPath);
this.refreshProjectsTree();
}
- public refreshProjectsTree() {
- this.projectTreeViewProvider.load(this.projects);
+ public async addItemPrompt(treeNode: BaseProjectTreeItem, itemTypeName?: string) {
+ const project = this.getProjectContextFromTreeNode(treeNode);
+
+ if (!itemTypeName) {
+ let itemFriendlyNames: string[] = [];
+
+ for (const itemType of templateMap.projectScriptTypes) {
+ itemFriendlyNames.push(itemType.friendlyName);
+ }
+
+ itemTypeName = await vscode.window.showQuickPick(itemFriendlyNames, {
+ canPickMany: false
+ });
+
+ if (!itemTypeName) {
+ return; // user cancelled
+ }
+ }
+
+ const itemType = templateMap.projectScriptTypeMap[itemTypeName.toLocaleLowerCase()];
+ const itemObjectName = await this.promptForNewObjectName(itemType, project);
+
+ if (!itemObjectName) {
+ return; // user cancelled
+ }
+
+ // TODO: file already exists?
+
+ const newFileText = this.macroExpansion(itemType.templateScript, { 'OBJECT_NAME': itemObjectName });
+ const relativeFilePath = this.prependContextPath(treeNode, itemObjectName + '.sql');
+
+ const newEntry = await project.addScriptItem(relativeFilePath, newFileText);
+
+ vscode.commands.executeCommand('vscode.open', newEntry.fsUri);
+
+ this.refreshProjectsTree();
}
+
+ //#region Helper methods
+
+ private macroExpansion(template: string, macroDict: Record): string {
+ const macroIndicator = '@@';
+ let output = template;
+
+ for (const macro in macroDict) {
+ // check if value contains the macroIndicator, which could break expansion for successive macros
+ if (macroDict[macro].includes(macroIndicator)) {
+ throw new Error(`Macro value ${macroDict[macro]} is invalid because it contains ${macroIndicator}`);
+ }
+
+ output = output.replace(new RegExp(macroIndicator + macro + macroIndicator, 'g'), macroDict[macro]);
+ }
+
+ return output;
+ }
+
+ private getProjectContextFromTreeNode(treeNode: BaseProjectTreeItem): Project {
+ if (!treeNode) {
+ // TODO: prompt for which (currently-open) project when invoked via command pallet
+ throw new Error('TODO: prompt for which project when invoked via command pallet');
+ }
+
+ if (treeNode.root instanceof ProjectRootTreeItem) {
+ return (treeNode.root as ProjectRootTreeItem).project;
+ }
+ else {
+ throw new Error('"Add item" command invoked from unexpected location: ' + treeNode.uri.path);
+ }
+ }
+
+ private async promptForNewObjectName(itemType: templateMap.ProjectScriptType, _project: Project): Promise {
+ // TODO: ask project for suggested name that doesn't conflict
+ const suggestedName = itemType.friendlyName.replace(new RegExp('\s', 'g'), '') + '1';
+
+ const itemObjectName = await vscode.window.showInputBox({
+ prompt: constants.newObjectNamePrompt(itemType.friendlyName),
+ value: suggestedName,
+ });
+
+ return itemObjectName;
+ }
+
+ private prependContextPath(treeNode: BaseProjectTreeItem, objectName: string): string {
+ if (treeNode instanceof FolderNode) {
+ return path.join(utils.trimUri(treeNode.root.uri, treeNode.uri), objectName);
+ }
+ else {
+ return objectName;
+ }
+ }
+
+ //#endregion
}
diff --git a/extensions/sql-database-projects/src/models/dataSources/dataSources.ts b/extensions/sql-database-projects/src/models/dataSources/dataSources.ts
index bc13b46b96..ce2339fd78 100644
--- a/extensions/sql-database-projects/src/models/dataSources/dataSources.ts
+++ b/extensions/sql-database-projects/src/models/dataSources/dataSources.ts
@@ -13,13 +13,21 @@ import { SqlConnectionDataSource } from './sqlConnectionStringSource';
export abstract class DataSource {
public name: string;
public abstract get type(): string;
- public abstract get friendlyName(): string;
+ public abstract get typeFriendlyName(): string;
constructor(name: string) {
this.name = name;
}
}
+export class NoDataSourcesFileError extends Error {
+ constructor(message?: string) {
+ super(message);
+ Object.setPrototypeOf(this, new.target.prototype);
+ this.name = NoDataSourcesFileError.name;
+ }
+}
+
/**
* parses the specified file to load DataSource objects
*/
@@ -30,7 +38,8 @@ export async function load(dataSourcesFilePath: string): Promise {
fileContents = await fs.readFile(dataSourcesFilePath);
}
catch (err) {
- throw new Error(constants.noDataSourcesFile);
+ // TODO: differentiate between file not existing and other types of failures; need to know whether to prompt to create new
+ throw new NoDataSourcesFileError(constants.noDataSourcesFile);
}
const rawJsonContents = JSON.parse(fileContents.toString());
diff --git a/extensions/sql-database-projects/src/models/dataSources/sqlConnectionStringSource.ts b/extensions/sql-database-projects/src/models/dataSources/sqlConnectionStringSource.ts
index fdd4427602..197b56d745 100644
--- a/extensions/sql-database-projects/src/models/dataSources/sqlConnectionStringSource.ts
+++ b/extensions/sql-database-projects/src/models/dataSources/sqlConnectionStringSource.ts
@@ -21,7 +21,7 @@ export class SqlConnectionDataSource extends DataSource {
return SqlConnectionDataSource.type;
}
- public get friendlyName(): string {
+ public get typeFriendlyName(): string {
return constants.sqlConnectionStringFriendly;
}
@@ -42,6 +42,10 @@ export class SqlConnectionDataSource extends DataSource {
}
}
+ public getSetting(settingName: string): string {
+ return this.connectionStringComponents[settingName];
+ }
+
public static fromJson(json: DataSourceJson): SqlConnectionDataSource {
return new SqlConnectionDataSource(json.name, (json.data as unknown as SqlConnectionDataSourceJson).connectionString);
}
diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts
index c36ccc614c..3bae437377 100644
--- a/extensions/sql-database-projects/src/models/project.ts
+++ b/extensions/sql-database-projects/src/models/project.ts
@@ -4,39 +4,40 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
-import * as xml2js from 'xml2js';
import * as path from 'path';
+import * as xmldom from 'xmldom';
+import * as constants from '../common/constants';
+
import { promises as fs } from 'fs';
import { DataSource } from './dataSources/dataSources';
+import { getErrorMessage } from '../common/utils';
/**
* Class representing a Project, and providing functions for operating on it
*/
export class Project {
- public projectFile: string;
+ public projectFilePath: string;
public files: ProjectEntry[] = [];
public dataSources: DataSource[] = [];
+ public get projectFolderPath() {
+ return path.dirname(this.projectFilePath);
+ }
+
+ private projFileXmlDoc: any = undefined;
+
constructor(projectFilePath: string) {
- this.projectFile = projectFilePath;
+ this.projectFilePath = projectFilePath;
}
/**
* Reads the project setting and contents from the file
*/
public async readProjFile() {
- let projFileContents = await fs.readFile(this.projectFile);
-
- const parser = new xml2js.Parser({
- explicitArray: true,
- explicitCharkey: false,
- explicitRoot: false
- });
-
- let result;
+ const projFileText = await fs.readFile(this.projectFilePath);
try {
- result = await parser.parseStringPromise(projFileContents.toString());
+ this.projFileXmlDoc = new xmldom.DOMParser().parseFromString(projFileText.toString());
}
catch (err) {
vscode.window.showErrorMessage(err);
@@ -45,23 +46,115 @@ export class Project {
// find all folders and files to include
- for (const itemGroup of result['ItemGroup']) {
- if (itemGroup['Build'] !== undefined) {
- for (const fileEntry of itemGroup['Build']) {
- this.files.push(this.createProjectEntry(fileEntry.$['Include'], EntryType.File));
- }
+ for (let ig = 0; ig < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; ig++) {
+ const itemGroup = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup)[ig];
+
+ for (let b = 0; b < itemGroup.getElementsByTagName(constants.Build).length; b++) {
+ this.files.push(this.createProjectEntry(itemGroup.getElementsByTagName(constants.Build)[b].getAttribute(constants.Include), EntryType.File));
}
- if (itemGroup['Folder'] !== undefined) {
- for (const folderEntry of itemGroup['Folder']) {
- this.files.push(this.createProjectEntry(folderEntry.$['Include'], EntryType.Folder));
- }
+ for (let f = 0; f < itemGroup.getElementsByTagName(constants.Folder).length; f++) {
+ this.files.push(this.createProjectEntry(itemGroup.getElementsByTagName(constants.Folder)[f].getAttribute(constants.Include), EntryType.Folder));
}
}
}
+ /**
+ * Adds a folder to the project, and saves the project file
+ * @param relativeFolderPath Relative path of the folder
+ */
+ public async addFolderItem(relativeFolderPath: string): Promise {
+ const absoluteFolderPath = path.join(this.projectFolderPath, relativeFolderPath);
+ await fs.mkdir(absoluteFolderPath, { recursive: true });
+
+ const folderEntry = this.createProjectEntry(relativeFolderPath, EntryType.Folder);
+ this.files.push(folderEntry);
+
+ await this.addToProjFile(folderEntry);
+ return folderEntry;
+ }
+
+ /**
+ * Writes a file to disk, adds that file to the project, and writes it to disk
+ * @param relativeFilePath Relative path of the file
+ * @param contents Contents to be written to the new file
+ */
+ public async addScriptItem(relativeFilePath: string, contents: string): Promise {
+ const absoluteFilePath = path.join(this.projectFolderPath, relativeFilePath);
+ await fs.mkdir(path.dirname(absoluteFilePath), { recursive: true });
+ await fs.writeFile(absoluteFilePath, contents);
+
+ const fileEntry = this.createProjectEntry(relativeFilePath, EntryType.File);
+ this.files.push(fileEntry);
+
+ await this.addToProjFile(fileEntry);
+
+ return fileEntry;
+ }
+
private createProjectEntry(relativePath: string, entryType: EntryType): ProjectEntry {
- return new ProjectEntry(vscode.Uri.file(path.join(this.projectFile, relativePath)), entryType);
+ return new ProjectEntry(vscode.Uri.file(path.join(this.projectFolderPath, relativePath)), relativePath, entryType);
+ }
+
+ private findOrCreateItemGroup(containedTag?: string): any {
+ let outputItemGroup = undefined;
+
+ // find any ItemGroup node that contains files; that's where we'll add
+ for (let i = 0; i < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; i++) {
+ const currentItemGroup = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup)[i];
+
+ // if we're not hunting for a particular child type, or if we are and we find it, use the ItemGroup
+ if (!containedTag || currentItemGroup.getElementsByTagName(containedTag).length > 0) {
+ outputItemGroup = currentItemGroup;
+ break;
+ }
+ }
+
+ // if none already exist, make a new ItemGroup for it
+ if (!outputItemGroup) {
+ outputItemGroup = this.projFileXmlDoc.createElement(constants.ItemGroup);
+ this.projFileXmlDoc.documentElement.appendChild(outputItemGroup);
+ }
+
+ return outputItemGroup;
+ }
+
+ private addFileToProjFile(path: string) {
+ const newFileNode = this.projFileXmlDoc.createElement(constants.Build);
+ newFileNode.setAttribute(constants.Include, path);
+
+ this.findOrCreateItemGroup(constants.Build).appendChild(newFileNode);
+ }
+
+ private addFolderToProjFile(path: string) {
+ const newFolderNode = this.projFileXmlDoc.createElement(constants.Folder);
+ newFolderNode.setAttribute(constants.Include, path);
+
+ this.findOrCreateItemGroup(constants.Folder).appendChild(newFolderNode);
+ }
+
+ private async addToProjFile(entry: ProjectEntry) {
+ try {
+ switch (entry.type) {
+ case EntryType.File:
+ this.addFileToProjFile(entry.relativePath);
+ break;
+ case EntryType.Folder:
+ this.addFolderToProjFile(entry.relativePath);
+ }
+
+ await this.serializeToProjFile(this.projFileXmlDoc);
+ }
+ catch (err) {
+ vscode.window.showErrorMessage(getErrorMessage(err));
+ return;
+ }
+ }
+
+ private async serializeToProjFile(projFileContents: any) {
+ const xml = new xmldom.XMLSerializer().serializeToString(projFileContents); // TODO: how to get this to serialize with "pretty" formatting
+
+ await fs.writeFile(this.projectFilePath, xml);
}
}
@@ -72,16 +165,18 @@ export class ProjectEntry {
/**
* Absolute file system URI
*/
- uri: vscode.Uri;
+ fsUri: vscode.Uri;
+ relativePath: string;
type: EntryType;
- constructor(uri: vscode.Uri, type: EntryType) {
- this.uri = uri;
+ constructor(uri: vscode.Uri, relativePath: string, type: EntryType) {
+ this.fsUri = uri;
+ this.relativePath = relativePath;
this.type = type;
}
public toString(): string {
- return this.uri.path;
+ return this.fsUri.path;
}
}
diff --git a/extensions/sql-database-projects/src/models/tree/baseTreeItem.ts b/extensions/sql-database-projects/src/models/tree/baseTreeItem.ts
index 9d5ac1def1..868d61f73b 100644
--- a/extensions/sql-database-projects/src/models/tree/baseTreeItem.ts
+++ b/extensions/sql-database-projects/src/models/tree/baseTreeItem.ts
@@ -52,3 +52,5 @@ export class MessageTreeItem extends BaseProjectTreeItem {
return new vscode.TreeItem(this.message, vscode.TreeItemCollapsibleState.None);
}
}
+
+export const SpacerTreeItem = new MessageTreeItem('');
diff --git a/extensions/sql-database-projects/src/models/tree/dataSourceTreeItem.ts b/extensions/sql-database-projects/src/models/tree/dataSourceTreeItem.ts
index ddc0e6f6d5..9f80cf4da4 100644
--- a/extensions/sql-database-projects/src/models/tree/dataSourceTreeItem.ts
+++ b/extensions/sql-database-projects/src/models/tree/dataSourceTreeItem.ts
@@ -53,7 +53,7 @@ export class SqlConnectionDataSourceTreeItem extends DataSourceTreeItem {
public get treeItem(): vscode.TreeItem {
let item = new vscode.TreeItem(this.uri, vscode.TreeItemCollapsibleState.Collapsed);
- item.label = `${this.dataSource.name} (${this.dataSource.friendlyName})`;
+ item.label = `${this.dataSource.name} (${this.dataSource.typeFriendlyName})`;
return item;
}
diff --git a/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts b/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts
index f26038d9a7..cc6a08c791 100644
--- a/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts
+++ b/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts
@@ -50,7 +50,17 @@ export class FileNode extends BaseProjectTreeItem {
}
public get treeItem(): vscode.TreeItem {
- return new vscode.TreeItem(this.uri, vscode.TreeItemCollapsibleState.None);
+ const treeItem = new vscode.TreeItem(this.uri, vscode.TreeItemCollapsibleState.None);
+
+ treeItem.command = {
+ title: 'Open file',
+ command: 'vscode.open',
+ arguments: [this.fileSystemUri]
+ };
+
+ treeItem.contextValue = 'File';
+
+ return treeItem;
}
}
@@ -58,7 +68,7 @@ export class FileNode extends BaseProjectTreeItem {
* Converts a full filesystem URI to a project-relative URI that's compatible with the project tree
*/
function fsPathToProjectUri(fileSystemUri: vscode.Uri, projectNode: ProjectRootTreeItem): vscode.Uri {
- const projBaseDir = path.dirname(projectNode.project.projectFile);
+ const projBaseDir = path.dirname(projectNode.project.projectFilePath);
let localUri = '';
if (fileSystemUri.fsPath.startsWith(projBaseDir)) {
diff --git a/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts b/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts
index 34e7cc7e5c..0a58f020fa 100644
--- a/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts
+++ b/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts
@@ -20,7 +20,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
project: Project;
constructor(project: Project) {
- super(vscode.Uri.parse(path.basename(project.projectFile)), undefined);
+ super(vscode.Uri.parse(path.basename(project.projectFilePath)), undefined);
this.project = project;
this.dataSourceNode = new DataSourcesTreeItem(this);
@@ -57,16 +57,16 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
switch (entry.type) {
case EntryType.File:
- newNode = new fileTree.FileNode(entry.uri, parentNode);
+ newNode = new fileTree.FileNode(entry.fsUri, parentNode);
break;
case EntryType.Folder:
- newNode = new fileTree.FolderNode(entry.uri, parentNode);
+ newNode = new fileTree.FolderNode(entry.fsUri, parentNode);
break;
default:
throw new Error(`Unknown EntryType: '${entry.type}'`);
}
- parentNode.fileChildren[path.basename(entry.uri.path)] = newNode;
+ parentNode.fileChildren[path.basename(entry.fsUri.path)] = newNode;
}
}
@@ -74,7 +74,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
* Gets the immediate parent tree node for an entry in a project file
*/
private getEntryParentNode(entry: ProjectEntry): fileTree.FolderNode | ProjectRootTreeItem {
- const relativePathParts = utils.trimChars(utils.trimUri(vscode.Uri.file(this.project.projectFile), entry.uri), '/').split('/').slice(0, -1); // remove the last part because we only care about the parent
+ const relativePathParts = utils.trimChars(utils.trimUri(vscode.Uri.file(this.project.projectFilePath), entry.fsUri), '/').split('/').slice(0, -1); // remove the last part because we only care about the parent
if (relativePathParts.length === 0) {
return this; // if nothing left after trimming the entry itself, must been root
@@ -84,7 +84,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
for (const part of relativePathParts) {
if (current.fileChildren[part] === undefined) {
- current.fileChildren[part] = new fileTree.FolderNode(vscode.Uri.file(path.join(path.dirname(this.project.projectFile), part)), current);
+ current.fileChildren[part] = new fileTree.FolderNode(vscode.Uri.file(path.join(path.dirname(this.project.projectFilePath), part)), current);
}
if (current.fileChildren[part] instanceof fileTree.FileNode) {
diff --git a/extensions/sql-database-projects/src/templates/templateMap.ts b/extensions/sql-database-projects/src/templates/templateMap.ts
new file mode 100644
index 0000000000..ba5c2143d7
--- /dev/null
+++ b/extensions/sql-database-projects/src/templates/templateMap.ts
@@ -0,0 +1,43 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as constants from '../common/constants';
+import * as templates from './templates';
+
+export class ProjectScriptType {
+ type: string;
+ friendlyName: string;
+ templateScript: string;
+
+ constructor(type: string, friendlyName: string, templateScript: string) {
+ this.type = type;
+ this.friendlyName = friendlyName;
+ this.templateScript = templateScript;
+ }
+}
+
+export const script: string = 'script';
+export const table: string = 'table';
+export const view: string = 'view';
+export const storedProcedure: string = 'storedProcedure';
+export const folder: string = 'folder';
+
+export const projectScriptTypes: ProjectScriptType[] = [
+ new ProjectScriptType(script, constants.scriptFriendlyName, templates.newSqlScriptTemplate),
+ new ProjectScriptType(table, constants.tableFriendlyName, templates.newSqlTableTemplate),
+ new ProjectScriptType(view, constants.viewFriendlyName, templates.newSqlViewTemplate),
+ new ProjectScriptType(storedProcedure, constants.storedProcedureFriendlyName, templates.newSqlStoredProcedureTemplate),
+];
+
+export const projectScriptTypeMap: Record = {};
+
+for (const scriptType of projectScriptTypes) {
+ if (Object.keys(projectScriptTypeMap).find(s => s === scriptType.type.toLocaleLowerCase() || s === scriptType.friendlyName.toLocaleLowerCase())) {
+ throw new Error(`Script type map already contains ${scriptType.type} or its friendlyName.`);
+ }
+
+ projectScriptTypeMap[scriptType.type.toLocaleLowerCase()] = scriptType;
+ projectScriptTypeMap[scriptType.friendlyName.toLocaleLowerCase()] = scriptType;
+}
diff --git a/extensions/sql-database-projects/src/templates/templates.ts b/extensions/sql-database-projects/src/templates/templates.ts
new file mode 100644
index 0000000000..f2a6d65d1b
--- /dev/null
+++ b/extensions/sql-database-projects/src/templates/templates.ts
@@ -0,0 +1,30 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as path from 'path';
+import { promises as fs } from 'fs';
+
+// Project templates
+export let newSqlProjectTemplate: string;
+
+// Script templates
+
+export let newSqlScriptTemplate: string;
+export let newSqlTableTemplate: string;
+export let newSqlViewTemplate: string;
+export let newSqlStoredProcedureTemplate: string;
+
+export async function loadTemplates(templateFolderPath: string) {
+ newSqlProjectTemplate = await loadTemplate(templateFolderPath, 'newSqlProjectTemplate.xml');
+
+ newSqlScriptTemplate = await loadTemplate(templateFolderPath, 'newTsqlScriptTemplate.sql');
+ newSqlTableTemplate = await loadTemplate(templateFolderPath, 'newTsqlTableTemplate.sql');
+ newSqlViewTemplate = await loadTemplate(templateFolderPath, 'newTsqlViewTemplate.sql');
+ newSqlStoredProcedureTemplate = await loadTemplate(templateFolderPath, 'newTsqlStoredProcedureTemplate.sql');
+}
+
+async function loadTemplate(templateFolderPath: string, fileName: string): Promise {
+ return (await fs.readFile(path.join(templateFolderPath, fileName))).toString();
+}
diff --git a/extensions/sql-database-projects/src/test/baselines/baselines.ts b/extensions/sql-database-projects/src/test/baselines/baselines.ts
new file mode 100644
index 0000000000..adfd32405d
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/baselines/baselines.ts
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as path from 'path';
+import { promises as fs } from 'fs';
+
+// Project baselines
+export let newProjectFileBaseline: string;
+export let openProjectFileBaseline: string;
+export let openDataSourcesBaseline: string;
+
+const baselineFolderPath = __dirname;
+
+export async function loadBaselines() {
+ newProjectFileBaseline = await loadBaseline(baselineFolderPath, 'newSqlProjectBaseline.xml');
+ openProjectFileBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectBaseline.xml');
+ openDataSourcesBaseline = await loadBaseline(baselineFolderPath, 'openDataSourcesBaseline.json');
+}
+
+async function loadBaseline(baselineFolderPath: string, fileName: string): Promise {
+ return (await fs.readFile(path.join(baselineFolderPath, fileName))).toString();
+}
diff --git a/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml b/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml
new file mode 100644
index 0000000000..93d952c88a
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml
@@ -0,0 +1,60 @@
+
+
+
+ Debug
+ AnyCPU
+ TestProjectName
+ 2.0
+ 4.1
+ {BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}
+ Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider
+ Database
+
+
+ TestProjectName
+ TestProjectName
+ 1033, CI
+ BySchemaAndSchemaType
+ True
+ v4.5
+ CS
+ Properties
+ False
+ True
+ True
+
+
+ bin\Release\
+ $(MSBuildProjectName).sql
+ False
+ pdbonly
+ true
+ false
+ true
+ prompt
+ 4
+
+
+ bin\Debug\
+ $(MSBuildProjectName).sql
+ false
+ true
+ full
+ false
+ true
+ true
+ prompt
+ 4
+
+
+ 11.0
+
+ True
+ 11.0
+
+
+
+
+
+
+
diff --git a/extensions/sql-database-projects/src/test/baselines/openDataSourcesBaseline.json b/extensions/sql-database-projects/src/test/baselines/openDataSourcesBaseline.json
new file mode 100644
index 0000000000..21d0f34f10
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/baselines/openDataSourcesBaseline.json
@@ -0,0 +1,21 @@
+{
+ "version": "0.0.0",
+ "datasources" : [
+ {
+ "name": "Test Data Source 1",
+ "type": "sql_connection_string",
+ "version": "0.0.0",
+ "data": {
+ "connectionString": "Data Source=.;Initial Catalog=testDb;Integrated Security=True"
+ }
+ },
+ {
+ "name": "My Other Data Source",
+ "type": "sql_connection_string",
+ "version": "0.0.0",
+ "data": {
+ "connectionString": "Data Source=.;Initial Catalog=testDb2;Integrated Security=False"
+ }
+ }
+ ]
+}
diff --git a/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml b/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml
new file mode 100644
index 0000000000..1ee9075d77
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml
@@ -0,0 +1,72 @@
+
+
+
+ Debug
+ AnyCPU
+ TestProjectName
+ 2.0
+ 4.1
+ {BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}
+ Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider
+ Database
+
+
+ TestProjectName
+ TestProjectName
+ 1033, CI
+ BySchemaAndSchemaType
+ True
+ v4.5
+ CS
+ Properties
+ False
+ True
+ True
+
+
+ bin\Release\
+ $(MSBuildProjectName).sql
+ False
+ pdbonly
+ true
+ false
+ true
+ prompt
+ 4
+
+
+ bin\Debug\
+ $(MSBuildProjectName).sql
+ false
+ true
+ full
+ false
+ true
+ true
+ prompt
+ 4
+
+
+ 11.0
+
+ True
+ 11.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/sql-database-projects/src/test/datasource.test.ts b/extensions/sql-database-projects/src/test/datasource.test.ts
new file mode 100644
index 0000000000..93d6c60a9a
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/datasource.test.ts
@@ -0,0 +1,30 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as should from 'should';
+import * as baselines from './baselines/baselines';
+import * as testUtils from './testUtils';
+import * as sql from '../models/dataSources/sqlConnectionStringSource';
+import * as dataSources from '../models/dataSources/dataSources';
+
+describe('Data Sources: DataSource operations', function (): void {
+ before(async function () : Promise {
+ await baselines.loadBaselines();
+ });
+
+ it('Should read DataSources from datasource.json', async function (): Promise {
+ const dataSourcePath = await testUtils.createTestDataSources(baselines.openDataSourcesBaseline);
+ const dataSourceList = await dataSources.load(dataSourcePath);
+
+ should(dataSourceList.length).equal(2);
+
+ should(dataSourceList[0].name).equal('Test Data Source 1');
+ should(dataSourceList[0].type).equal(sql.SqlConnectionDataSource.type);
+ should((dataSourceList[0] as sql.SqlConnectionDataSource).getSetting('Initial Catalog')).equal('testDb');
+
+ should(dataSourceList[1].name).equal('My Other Data Source');
+ should((dataSourceList[1] as sql.SqlConnectionDataSource).getSetting('Integrated Security')).equal('False');
+ });
+});
diff --git a/extensions/sql-database-projects/src/test/index.ts b/extensions/sql-database-projects/src/test/index.ts
new file mode 100644
index 0000000000..6264dd975e
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/index.ts
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as path from 'path';
+const testRunner = require('vscodetestcover');
+
+const suite = 'Database Projects Extension Tests';
+
+const mochaOptions: any = {
+ ui: 'bdd',
+ useColors: true,
+ timeout: 10000
+};
+
+// set relevant mocha options from the environment
+if (process.env.ADS_TEST_GREP) {
+ mochaOptions.grep = process.env.ADS_TEST_GREP;
+ console.log(`setting options.grep to: ${mochaOptions.grep}`);
+}
+if (process.env.ADS_TEST_INVERT_GREP) {
+ mochaOptions.invert = parseInt(process.env.ADS_TEST_INVERT_GREP);
+ console.log(`setting options.invert to: ${mochaOptions.invert}`);
+}
+if (process.env.ADS_TEST_TIMEOUT) {
+ mochaOptions.timeout = parseInt(process.env.ADS_TEST_TIMEOUT);
+ console.log(`setting options.timeout to: ${mochaOptions.timeout}`);
+}
+if (process.env.ADS_TEST_RETRIES) {
+ mochaOptions.retries = parseInt(process.env.ADS_TEST_RETRIES);
+ console.log(`setting options.retries to: ${mochaOptions.retries}`);
+}
+
+if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
+ mochaOptions.reporter = 'mocha-multi-reporters';
+ mochaOptions.reporterOptions = {
+ reporterEnabled: 'spec, mocha-junit-reporter',
+ mochaJunitReporterReporterOptions: {
+ testsuitesTitle: `${suite} ${process.platform}`,
+ mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
+ }
+ };
+}
+
+testRunner.configure(mochaOptions, { coverConfig: '../../coverConfig.json' });
+
+export = testRunner;
diff --git a/extensions/sql-database-projects/src/test/project.test.ts b/extensions/sql-database-projects/src/test/project.test.ts
new file mode 100644
index 0000000000..89e8e78eb0
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/project.test.ts
@@ -0,0 +1,57 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as should from 'should';
+import * as path from 'path';
+import * as baselines from './baselines/baselines';
+import * as testUtils from './testUtils';
+
+import { promises as fs } from 'fs';
+import { Project, EntryType } from '../models/project';
+
+let projFilePath: string;
+
+describe('Project: sqlproj content operations', function (): void {
+ before(async function () : Promise {
+ await baselines.loadBaselines();
+ });
+
+ beforeEach(async () => {
+ projFilePath = await testUtils.createTestSqlProj(baselines.openProjectFileBaseline);
+ });
+
+ it('Should read Project from sqlproj', async function (): Promise {
+ const project: Project = new Project(projFilePath);
+ await project.readProjFile();
+
+ should(project.files.filter(f => f.type === EntryType.File).length).equal(4);
+ should(project.files.filter(f => f.type === EntryType.Folder).length).equal(5);
+
+ should(project.files.find(f => f.type === EntryType.Folder && f.relativePath === 'Views\\User')).not.equal(undefined); // mixed ItemGroup folder
+ should(project.files.find(f => f.type === EntryType.File && f.relativePath === 'Views\\User\\Profile.sql')).not.equal(undefined); // mixed ItemGroup file
+ });
+
+ it('Should add Folder and Build entries to sqlproj', async function (): Promise {
+ const project: Project = new Project(projFilePath);
+ await project.readProjFile();
+
+ const folderPath = 'Stored Procedures';
+ const filePath = path.join(folderPath, 'Fake Stored Proc.sql');
+ const fileContents = 'SELECT \'This is not actually a stored procedure.\'';
+
+ await project.addFolderItem(folderPath);
+ await project.addScriptItem(filePath, fileContents);
+
+ const newProject = new Project(projFilePath);
+ await newProject.readProjFile();
+
+ should(newProject.files.find(f => f.type === EntryType.Folder && f.relativePath === folderPath)).not.equal(undefined);
+ should(newProject.files.find(f => f.type === EntryType.File && f.relativePath === filePath)).not.equal(undefined);
+
+ const newFileContents = (await fs.readFile(path.join(newProject.projectFolderPath, filePath))).toString();
+
+ should (newFileContents).equal(fileContents);
+ });
+});
diff --git a/extensions/sql-database-projects/src/test/projectController.test.ts b/extensions/sql-database-projects/src/test/projectController.test.ts
new file mode 100644
index 0000000000..7f3e980cd5
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/projectController.test.ts
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as should from 'should';
+import * as path from 'path';
+import * as os from 'os';
+import * as vscode from 'vscode';
+import * as baselines from './baselines/baselines';
+import * as templates from '../templates/templates';
+import * as testUtils from './testUtils';
+
+import { SqlDatabaseProjectTreeViewProvider } from '../controllers/databaseProjectTreeViewProvider';
+import { ProjectsController } from '../controllers/projectController';
+import { promises as fs } from 'fs';
+
+describe('ProjectsController: project controller operations', function (): void {
+ before(async function () : Promise {
+ await templates.loadTemplates(path.join(__dirname, '..', '..', 'resources', 'templates'));
+ await baselines.loadBaselines();
+ });
+
+ it('Should create new sqlproj file with correct values', async function (): Promise {
+ const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
+ const projFileDir = path.join(os.tmpdir(), `TestProject_${new Date().getTime()}`);
+
+ const projFilePath = await projController.createNewProject('TestProjectName', vscode.Uri.file(projFileDir), 'BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575');
+
+ let projFileText = (await fs.readFile(projFilePath)).toString();
+
+ should(projFileText).equal(baselines.newProjectFileBaseline);
+ });
+
+ it('Should load Project and associated DataSources', async function (): Promise {
+ // setup test files
+ const folderPath = await testUtils.generateTestFolderPath();
+ const sqlProjPath = await testUtils.createTestSqlProj(baselines.openProjectFileBaseline, folderPath);
+ await testUtils.createTestDataSources(baselines.openDataSourcesBaseline, folderPath);
+
+ const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
+
+ const project = await projController.openProject(vscode.Uri.file(sqlProjPath));
+
+ should(project.files.length).equal(9); // detailed sqlproj tests in their own test file
+ should(project.dataSources.length).equal(2); // detailed datasources tests in their own test file
+ });
+});
diff --git a/extensions/sql-database-projects/src/test/testUtils.ts b/extensions/sql-database-projects/src/test/testUtils.ts
new file mode 100644
index 0000000000..d000f8c95a
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/testUtils.ts
@@ -0,0 +1,35 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as path from 'path';
+import * as os from 'os';
+import * as constants from '../common/constants';
+
+import { promises as fs } from 'fs';
+
+export async function createTestSqlProj(contents: string, folderPath?: string): Promise {
+ return await createTestFile(contents, 'TestProject.sqlproj', folderPath);
+}
+
+export async function createTestDataSources(contents: string, folderPath?: string): Promise {
+ return await createTestFile(contents, constants.dataSourcesFileName, folderPath);
+}
+
+export async function generateTestFolderPath(): Promise {
+ const folderPath = path.join(os.tmpdir(), `TestProject_${new Date().getTime()}`);
+ await fs.mkdir(folderPath, { recursive: true });
+
+ return folderPath;
+}
+
+async function createTestFile(contents: string, fileName: string, folderPath?: string): Promise {
+ folderPath = folderPath ?? await generateTestFolderPath();
+ const filePath = path.join(folderPath, fileName);
+
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
+ await fs.writeFile(filePath, contents);
+
+ return filePath;
+}
diff --git a/extensions/sql-database-projects/yarn.lock b/extensions/sql-database-projects/yarn.lock
index 1440fb8059..e994a94df2 100644
--- a/extensions/sql-database-projects/yarn.lock
+++ b/extensions/sql-database-projects/yarn.lock
@@ -9,6 +9,134 @@
dependencies:
"@babel/highlight" "^7.0.0"
+"@babel/code-frame@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
+ integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
+ dependencies:
+ "@babel/highlight" "^7.8.3"
+
+"@babel/core@^7.7.5":
+ version "7.9.0"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
+ integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==
+ dependencies:
+ "@babel/code-frame" "^7.8.3"
+ "@babel/generator" "^7.9.0"
+ "@babel/helper-module-transforms" "^7.9.0"
+ "@babel/helpers" "^7.9.0"
+ "@babel/parser" "^7.9.0"
+ "@babel/template" "^7.8.6"
+ "@babel/traverse" "^7.9.0"
+ "@babel/types" "^7.9.0"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.1"
+ json5 "^2.1.2"
+ lodash "^4.17.13"
+ resolve "^1.3.2"
+ semver "^5.4.1"
+ source-map "^0.5.0"
+
+"@babel/generator@^7.9.0", "@babel/generator@^7.9.5":
+ version "7.9.5"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9"
+ integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==
+ dependencies:
+ "@babel/types" "^7.9.5"
+ jsesc "^2.5.1"
+ lodash "^4.17.13"
+ source-map "^0.5.0"
+
+"@babel/helper-function-name@^7.9.5":
+ version "7.9.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c"
+ integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.8.3"
+ "@babel/template" "^7.8.3"
+ "@babel/types" "^7.9.5"
+
+"@babel/helper-get-function-arity@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5"
+ integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==
+ dependencies:
+ "@babel/types" "^7.8.3"
+
+"@babel/helper-member-expression-to-functions@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c"
+ integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==
+ dependencies:
+ "@babel/types" "^7.8.3"
+
+"@babel/helper-module-imports@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498"
+ integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==
+ dependencies:
+ "@babel/types" "^7.8.3"
+
+"@babel/helper-module-transforms@^7.9.0":
+ version "7.9.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5"
+ integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==
+ dependencies:
+ "@babel/helper-module-imports" "^7.8.3"
+ "@babel/helper-replace-supers" "^7.8.6"
+ "@babel/helper-simple-access" "^7.8.3"
+ "@babel/helper-split-export-declaration" "^7.8.3"
+ "@babel/template" "^7.8.6"
+ "@babel/types" "^7.9.0"
+ lodash "^4.17.13"
+
+"@babel/helper-optimise-call-expression@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9"
+ integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==
+ dependencies:
+ "@babel/types" "^7.8.3"
+
+"@babel/helper-replace-supers@^7.8.6":
+ version "7.8.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8"
+ integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==
+ dependencies:
+ "@babel/helper-member-expression-to-functions" "^7.8.3"
+ "@babel/helper-optimise-call-expression" "^7.8.3"
+ "@babel/traverse" "^7.8.6"
+ "@babel/types" "^7.8.6"
+
+"@babel/helper-simple-access@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae"
+ integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==
+ dependencies:
+ "@babel/template" "^7.8.3"
+ "@babel/types" "^7.8.3"
+
+"@babel/helper-split-export-declaration@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9"
+ integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==
+ dependencies:
+ "@babel/types" "^7.8.3"
+
+"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5":
+ version "7.9.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
+ integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==
+
+"@babel/helpers@^7.9.0":
+ version "7.9.2"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f"
+ integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==
+ dependencies:
+ "@babel/template" "^7.8.3"
+ "@babel/traverse" "^7.9.0"
+ "@babel/types" "^7.9.0"
+
"@babel/highlight@^7.0.0":
version "7.5.0"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
@@ -18,17 +146,67 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
-"@types/node@*":
- version "13.1.2"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.2.tgz#fe94285bf5e0782e1a9e5a8c482b1c34465fa385"
- integrity sha512-B8emQA1qeKerqd1dmIsQYnXi+mmAzTB7flExjmy5X1aVAKFNNNDubkavwR13kR6JnpeLp3aLoJhwn9trWPAyFQ==
-
-"@types/xml2js@^0.4.5":
- version "0.4.5"
- resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.5.tgz#d21759b056f282d9c7066f15bbf5c19b908f22fa"
- integrity sha512-yohU3zMn0fkhlape1nxXG2bLEGZRc1FeqF80RoHaYXJN7uibaauXfhzhOJr1Xh36sn+/tx21QAOf07b/xYVk1w==
+"@babel/highlight@^7.8.3":
+ version "7.9.0"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079"
+ integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==
dependencies:
- "@types/node" "*"
+ "@babel/helper-validator-identifier" "^7.9.0"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.7.5", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0":
+ version "7.9.4"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8"
+ integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==
+
+"@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
+ version "7.8.6"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
+ integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==
+ dependencies:
+ "@babel/code-frame" "^7.8.3"
+ "@babel/parser" "^7.8.6"
+ "@babel/types" "^7.8.6"
+
+"@babel/traverse@^7.7.4", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
+ version "7.9.5"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2"
+ integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==
+ dependencies:
+ "@babel/code-frame" "^7.8.3"
+ "@babel/generator" "^7.9.5"
+ "@babel/helper-function-name" "^7.9.5"
+ "@babel/helper-split-export-declaration" "^7.8.3"
+ "@babel/parser" "^7.9.0"
+ "@babel/types" "^7.9.5"
+ debug "^4.1.0"
+ globals "^11.1.0"
+ lodash "^4.17.13"
+
+"@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
+ version "7.9.5"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444"
+ integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.9.5"
+ lodash "^4.17.13"
+ to-fast-properties "^2.0.0"
+
+"@istanbuljs/schema@^0.1.2":
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
+ integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
+
+"@types/xmldom@^0.1.29":
+ version "0.1.29"
+ resolved "https://registry.yarnpkg.com/@types/xmldom/-/xmldom-0.1.29.tgz#c4428b0ca86d3b881475726fd94980b38a27c381"
+ integrity sha1-xEKLDKhtO4gUdXJv2UmAs4onw4E=
+
+ansi-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+ integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
ansi-styles@^3.2.1:
version "3.2.1"
@@ -37,6 +215,13 @@ ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
+append-transform@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12"
+ integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==
+ dependencies:
+ default-require-extensions "^3.0.0"
+
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -57,11 +242,21 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.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==
+
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=
+callsite@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
+ integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
+
chalk@^2.0.0, chalk@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@@ -71,6 +266,16 @@ chalk@^2.0.0, chalk@^2.3.0:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
+charenc@~0.0.1:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
+ integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
+
+circular-json@^0.3.1:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
+ integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==
+
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -83,6 +288,11 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+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.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -93,12 +303,71 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+convert-source-map@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
+ integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+ dependencies:
+ safe-buffer "~5.1.1"
+
+crypt@~0.0.1:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
+ integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
+
+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:
+ 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"
+
+debug@^4.1.0, debug@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
+decache@^4.4.0:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/decache/-/decache-4.5.1.tgz#94a977a88a4188672c96550ec4889582ceecdf49"
+ integrity sha512-5J37nATc6FmOTLbcsr9qx7Nm28qQyg1SK4xyEHqM0IBkNhWFp0Sm+vKoWYHD8wq+OUEb9jLyaKFfzzd1A9hcoA==
+ dependencies:
+ callsite "^1.0.0"
+
+default-require-extensions@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96"
+ integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==
+ dependencies:
+ strip-bom "^4.0.0"
+
+diff@3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+ integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+
diff@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==
-escape-string-regexp@^1.0.5:
+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=
@@ -118,7 +387,24 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-glob@^7.1.1:
+gensync@^1.0.0-beta.1:
+ version "1.0.0-beta.1"
+ resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
+ integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==
+
+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, glob@^7.1.3:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -130,11 +416,36 @@ glob@^7.1.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+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==
+
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-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+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=
+
+html-escaper@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+ integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@@ -148,6 +459,69 @@ inherits@2:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+is-buffer@~1.1.1:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+
+istanbul-lib-coverage@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
+ integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
+
+istanbul-lib-coverage@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec"
+ integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==
+
+istanbul-lib-hook@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6"
+ integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==
+ dependencies:
+ append-transform "^2.0.0"
+
+istanbul-lib-instrument@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz#61f13ac2c96cfefb076fe7131156cc05907874e6"
+ integrity sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==
+ dependencies:
+ "@babel/core" "^7.7.5"
+ "@babel/parser" "^7.7.5"
+ "@babel/template" "^7.7.4"
+ "@babel/traverse" "^7.7.4"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-coverage "^3.0.0"
+ semver "^6.3.0"
+
+istanbul-lib-report@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6"
+ integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==
+ dependencies:
+ istanbul-lib-coverage "^3.0.0"
+ make-dir "^3.0.0"
+ supports-color "^7.1.0"
+
+istanbul-lib-source-maps@^3.0.6:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
+ integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
+ dependencies:
+ debug "^4.1.1"
+ istanbul-lib-coverage "^2.0.5"
+ make-dir "^2.1.0"
+ rimraf "^2.6.3"
+ source-map "^0.6.1"
+
+istanbul-reports@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b"
+ integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==
+ dependencies:
+ html-escaper "^2.0.0"
+ istanbul-lib-report "^3.0.0"
+
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -161,7 +535,48 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
-minimatch@^3.0.4:
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+json5@^2.1.2:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
+ integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
+ dependencies:
+ minimist "^1.2.5"
+
+lodash@^4.16.4, lodash@^4.17.13, lodash@^4.17.4:
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
+make-dir@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+ integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+ dependencies:
+ pify "^4.0.1"
+ semver "^5.6.0"
+
+make-dir@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392"
+ integrity sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==
+ dependencies:
+ semver "^6.0.0"
+
+md5@^2.1.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
+ integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=
+ dependencies:
+ charenc "~0.0.1"
+ crypt "~0.0.1"
+ is-buffer "~1.1.1"
+
+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==
@@ -173,13 +588,71 @@ minimist@0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-mkdirp@^0.5.1:
+minimist@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+ integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
+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"
+mkdirp@~0.5.1:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
+ integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
+ dependencies:
+ minimist "^1.2.5"
+
+mocha-junit-reporter@^1.17.0:
+ version "1.23.3"
+ resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.3.tgz#941e219dd759ed732f8641e165918aa8b167c981"
+ integrity sha512-ed8LqbRj1RxZfjt/oC9t12sfrWsjZ3gNnbhV1nuj9R/Jb5/P3Xb4duv2eCfCDMYH+fEu0mqca7m4wsiVjsxsvA==
+ dependencies:
+ debug "^2.2.0"
+ md5 "^2.1.0"
+ mkdirp "~0.5.1"
+ strip-ansi "^4.0.0"
+ xml "^1.0.0"
+
+mocha-multi-reporters@^1.1.7:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz#cc7f3f4d32f478520941d852abb64d9988587d82"
+ integrity sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=
+ dependencies:
+ debug "^3.1.0"
+ lodash "^4.16.4"
+
+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==
+
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -197,6 +670,16 @@ path-parse@^1.0.6:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+pify@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+ integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+postinstall-build@^5.0.1:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7"
+ integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg==
+
resolve@^1.3.2:
version "1.13.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
@@ -204,21 +687,106 @@ resolve@^1.3.2:
dependencies:
path-parse "^1.0.6"
-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==
+rimraf@^2.6.3:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
-semver@^5.3.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==
+
+semver@^5.3.0, semver@^5.4.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+semver@^6.0.0, semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+should-equal@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3"
+ integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==
+ dependencies:
+ should-type "^1.4.0"
+
+should-format@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1"
+ integrity sha1-m/yPdPo5IFxT04w01xcwPidxJPE=
+ dependencies:
+ should-type "^1.3.0"
+ should-type-adaptors "^1.0.1"
+
+should-type-adaptors@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a"
+ integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==
+ dependencies:
+ should-type "^1.3.0"
+ should-util "^1.0.0"
+
+should-type@^1.3.0, should-type@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3"
+ integrity sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=
+
+should-util@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28"
+ integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==
+
+should@^13.2.1:
+ version "13.2.3"
+ resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10"
+ integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==
+ dependencies:
+ should-equal "^2.0.0"
+ should-format "^3.0.3"
+ should-type "^1.4.0"
+ should-type-adaptors "^1.0.1"
+ should-util "^1.0.0"
+
+source-map@^0.5.0:
+ 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.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
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=
+strip-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+ integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
+ dependencies:
+ ansi-regex "^3.0.0"
+
+strip-bom@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
+ integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
+
+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"
@@ -226,6 +794,18 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"
+supports-color@^7.1.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
+ integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
+ dependencies:
+ has-flag "^4.0.0"
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
+
tslib@^1.8.0, tslib@^1.8.1:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
@@ -257,30 +837,76 @@ tsutils@^2.29.0:
dependencies:
tslib "^1.8.1"
+typemoq@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/typemoq/-/typemoq-2.1.0.tgz#4452ce360d92cf2a1a180f0c29de2803f87af1e8"
+ integrity sha512-DtRNLb7x8yCTv/KHlwes+NI+aGb4Vl1iPC63Hhtcvk1DpxSAZzKWQv0RQFY0jX2Uqj0SDBNl8Na4e6MV6TNDgw==
+ dependencies:
+ circular-json "^0.3.1"
+ lodash "^4.17.4"
+ postinstall-build "^5.0.1"
+
typescript@^2.6.1:
version "2.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==
+vscode-jsonrpc@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz#9bab9c330d89f43fc8c1e8702b5c36e058a01794"
+ integrity sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==
+
+vscode-languageclient@^5.3.0-next.1:
+ version "5.3.0-next.9"
+ resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.9.tgz#34f58017647f15cd86015f7af45935dc750611f7"
+ integrity sha512-BFA3X1y2EI2CfsSBy0KG2Xr5BOYfd/97jTmD+doqL6oj+cY8S7AmRCOwb2f9Hbjq8GWL7YC+OJ0leZEUSPgP0A==
+ dependencies:
+ semver "^6.3.0"
+ vscode-languageserver-protocol "^3.15.0-next.8"
+
+vscode-languageserver-protocol@^3.15.0-next.8:
+ version "3.15.3"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz#3fa9a0702d742cf7883cb6182a6212fcd0a1d8bb"
+ integrity sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==
+ dependencies:
+ vscode-jsonrpc "^5.0.1"
+ vscode-languageserver-types "3.15.1"
+
+vscode-languageserver-types@3.15.1:
+ version "3.15.1"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
+ integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==
+
vscode-nls@^3.2.1:
version "3.2.5"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4"
integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw==
+"vscodetestcover@github:corivera/vscodetestcover#1.0.6":
+ version "1.0.5"
+ resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb"
+ dependencies:
+ decache "^4.4.0"
+ glob "^7.1.2"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-hook "^3.0.0"
+ istanbul-lib-instrument "^4.0.0"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^3.0.6"
+ istanbul-reports "^3.0.0"
+ mocha "^5.2.0"
+
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-xml2js@^0.4.23:
- version "0.4.23"
- resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
- integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
- dependencies:
- sax ">=0.6.0"
- xmlbuilder "~11.0.0"
+xml@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
+ 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.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.3.0.tgz#e625457f4300b5df9c2e1ecb776147ece47f3e5a"
+ integrity sha512-z9s6k3wxE+aZHgXYxSTpGDo7BYOUfJsIRyoZiX6HTjwpwfS2wpQBQKa2fD+ShLyPkqDYo5ud7KitmLZ2Cd6r0g==
diff --git a/scripts/test-extensions-unit.bat b/scripts/test-extensions-unit.bat
index 594411fb3e..a41fda7957 100755
--- a/scripts/test-extensions-unit.bat
+++ b/scripts/test-extensions-unit.bat
@@ -26,6 +26,8 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
call yarn gulp compile-extension:mssql
call yarn gulp compile-extension:notebook
call yarn gulp compile-extension:resource-deployment
+ call yarn gulp compile-extension:machine-learning-services
+ call yarn gulp compile-extension:sql-database-projects
echo "Running integration tests with '%INTEGRATION_TEST_ELECTRON_PATH%' as build."
)
@@ -89,6 +91,11 @@ REM echo *** starting mssql tests ***
REM echo ******************************************
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\mssql --extensionTestsPath=%~dp0\..\extensions\mssql\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu
+echo ********************************************
+echo *** starting sql-database-projects tests ***
+echo ********************************************
+call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\sql-database-projects --extensionTestsPath=%~dp0\..\extensions\sql-database-projects\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu
+
if %errorlevel% neq 0 exit /b %errorlevel%
rmdir /s /q %VSCODEUSERDATADIR%
diff --git a/scripts/test-extensions-unit.sh b/scripts/test-extensions-unit.sh
index 6395d15a30..591ce615eb 100755
--- a/scripts/test-extensions-unit.sh
+++ b/scripts/test-extensions-unit.sh
@@ -79,9 +79,9 @@ echo *** starting resource deployment tests ***
echo ******************************************
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX --extensionDevelopmentPath=$ROOT/extensions/resource-deployment --extensionTestsPath=$ROOT/extensions/resource-deployment/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR --disable-telemetry --disable-crash-reporter --disable-updates --nogpu
-echo ******************************************
+echo ************************************************
echo *** starting machine-learning-services tests ***
-echo ******************************************
+echo ************************************************
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX --extensionDevelopmentPath=$ROOT/extensions/machine-learning-services --extensionTestsPath=$ROOT/extensions/machine-learning-services/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR --disable-telemetry --disable-crash-reporter --disable-updates --nogpu
# echo ******************************************
@@ -89,5 +89,10 @@ echo ******************************************
# echo ******************************************
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX --extensionDevelopmentPath=$ROOT/extensions/mssql --extensionTestsPath=$ROOT/extensions/mssql/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR --disable-telemetry --disable-crash-reporter --disable-updates --nogpu
+echo ********************************************
+echo *** starting sql-database-projects tests ***
+echo ********************************************
+"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX --extensionDevelopmentPath=$ROOT/extensions/sql-database-projects --extensionTestsPath=$ROOT/extensions/sql-database-projects/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR --disable-telemetry --disable-crash-reporter --disable-updates --nogpu
+
rm -r $VSCODEUSERDATADIR
rm -r $VSCODEEXTDIR