mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Expose sql project apis (#15239)
* make project variables private and add getters * expose project in sqlproj.d.ts * add more comments * change to ISqlProject
This commit is contained in:
@@ -12,6 +12,7 @@ import * as os from 'os';
|
|||||||
import * as templates from '../templates/templates';
|
import * as templates from '../templates/templates';
|
||||||
|
|
||||||
import { Uri, window } from 'vscode';
|
import { Uri, window } from 'vscode';
|
||||||
|
import { IFileProjectEntry, ISqlProject } from 'sqldbproj';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { DataSource } from './dataSources/dataSources';
|
import { DataSource } from './dataSources/dataSources';
|
||||||
import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectReferenceSettings } from './IDatabaseReferenceSettings';
|
import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectReferenceSettings } from './IDatabaseReferenceSettings';
|
||||||
@@ -20,32 +21,76 @@ import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/t
|
|||||||
/**
|
/**
|
||||||
* Class representing a Project, and providing functions for operating on it
|
* Class representing a Project, and providing functions for operating on it
|
||||||
*/
|
*/
|
||||||
export class Project {
|
export class Project implements ISqlProject {
|
||||||
public projectFilePath: string;
|
private _projectFilePath: string;
|
||||||
public projectFileName: string;
|
private _projectFileName: string;
|
||||||
public projectGuid: string | undefined;
|
private _projectGuid: string | undefined;
|
||||||
public files: FileProjectEntry[] = [];
|
private _files: FileProjectEntry[] = [];
|
||||||
public dataSources: DataSource[] = [];
|
private _dataSources: DataSource[] = [];
|
||||||
public importedTargets: string[] = [];
|
private _importedTargets: string[] = [];
|
||||||
public databaseReferences: IDatabaseReferenceProjectEntry[] = [];
|
private _databaseReferences: IDatabaseReferenceProjectEntry[] = [];
|
||||||
public sqlCmdVariables: Record<string, string> = {};
|
private _sqlCmdVariables: Record<string, string> = {};
|
||||||
public preDeployScripts: FileProjectEntry[] = [];
|
private _preDeployScripts: FileProjectEntry[] = [];
|
||||||
public postDeployScripts: FileProjectEntry[] = [];
|
private _postDeployScripts: FileProjectEntry[] = [];
|
||||||
public noneDeployScripts: FileProjectEntry[] = [];
|
private _noneDeployScripts: FileProjectEntry[] = [];
|
||||||
|
|
||||||
public get dacpacOutputPath(): string {
|
public get dacpacOutputPath(): string {
|
||||||
return path.join(this.projectFolderPath, 'bin', 'Debug', `${this.projectFileName}.dacpac`);
|
return path.join(this.projectFolderPath, 'bin', 'Debug', `${this._projectFileName}.dacpac`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get projectFolderPath() {
|
public get projectFolderPath() {
|
||||||
return Uri.file(path.dirname(this.projectFilePath)).fsPath;
|
return Uri.file(path.dirname(this._projectFilePath)).fsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get projectFilePath(): string {
|
||||||
|
return this._projectFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get projectFileName(): string {
|
||||||
|
return this._projectFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get projectGuid(): string | undefined {
|
||||||
|
return this._projectGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get files(): FileProjectEntry[] {
|
||||||
|
return this._files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get dataSources(): DataSource[] {
|
||||||
|
return this._dataSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get importedTargets(): string[] {
|
||||||
|
return this._importedTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get databaseReferences(): IDatabaseReferenceProjectEntry[] {
|
||||||
|
return this._databaseReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get sqlCmdVariables(): Record<string, string> {
|
||||||
|
return this._sqlCmdVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get preDeployScripts(): FileProjectEntry[] {
|
||||||
|
return this._preDeployScripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get postDeployScripts(): FileProjectEntry[] {
|
||||||
|
return this._postDeployScripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get noneDeployScripts(): FileProjectEntry[] {
|
||||||
|
return this._noneDeployScripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private projFileXmlDoc: any = undefined;
|
private projFileXmlDoc: any = undefined;
|
||||||
|
|
||||||
constructor(projectFilePath: string) {
|
constructor(projectFilePath: string) {
|
||||||
this.projectFilePath = projectFilePath;
|
this._projectFilePath = projectFilePath;
|
||||||
this.projectFileName = path.basename(projectFilePath, '.sqlproj');
|
this._projectFileName = path.basename(projectFilePath, '.sqlproj');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,11 +110,11 @@ export class Project {
|
|||||||
public async readProjFile(): Promise<void> {
|
public async readProjFile(): Promise<void> {
|
||||||
this.resetProject();
|
this.resetProject();
|
||||||
|
|
||||||
const projFileText = await fs.readFile(this.projectFilePath);
|
const projFileText = await fs.readFile(this._projectFilePath);
|
||||||
this.projFileXmlDoc = new xmldom.DOMParser().parseFromString(projFileText.toString());
|
this.projFileXmlDoc = new xmldom.DOMParser().parseFromString(projFileText.toString());
|
||||||
|
|
||||||
// get projectGUID
|
// get projectGUID
|
||||||
this.projectGuid = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ProjectGuid)[0].childNodes[0].nodeValue;
|
this._projectGuid = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ProjectGuid)[0].childNodes[0].nodeValue;
|
||||||
|
|
||||||
// find all folders and files to include
|
// find all folders and files to include
|
||||||
for (let ig = 0; ig < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; ig++) {
|
for (let ig = 0; ig < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; ig++) {
|
||||||
@@ -77,14 +122,14 @@ export class Project {
|
|||||||
|
|
||||||
const buildElements = itemGroup.getElementsByTagName(constants.Build);
|
const buildElements = itemGroup.getElementsByTagName(constants.Build);
|
||||||
for (let b = 0; b < buildElements.length; b++) {
|
for (let b = 0; b < buildElements.length; b++) {
|
||||||
this.files.push(this.createFileProjectEntry(buildElements[b].getAttribute(constants.Include), EntryType.File, buildElements[b].getAttribute(constants.Type)));
|
this._files.push(this.createFileProjectEntry(buildElements[b].getAttribute(constants.Include), EntryType.File, buildElements[b].getAttribute(constants.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const folderElements = itemGroup.getElementsByTagName(constants.Folder);
|
const folderElements = itemGroup.getElementsByTagName(constants.Folder);
|
||||||
for (let f = 0; f < folderElements.length; f++) {
|
for (let f = 0; f < folderElements.length; f++) {
|
||||||
// don't add Properties folder since it isn't supported for now
|
// don't add Properties folder since it isn't supported for now
|
||||||
if (folderElements[f].getAttribute(constants.Include) !== constants.Properties) {
|
if (folderElements[f].getAttribute(constants.Include) !== constants.Properties) {
|
||||||
this.files.push(this.createFileProjectEntry(folderElements[f].getAttribute(constants.Include), EntryType.Folder));
|
this._files.push(this.createFileProjectEntry(folderElements[f].getAttribute(constants.Include), EntryType.Folder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +137,7 @@ export class Project {
|
|||||||
let preDeployScriptCount: number = 0;
|
let preDeployScriptCount: number = 0;
|
||||||
const preDeploy = itemGroup.getElementsByTagName(constants.PreDeploy);
|
const preDeploy = itemGroup.getElementsByTagName(constants.PreDeploy);
|
||||||
for (let pre = 0; pre < preDeploy.length; pre++) {
|
for (let pre = 0; pre < preDeploy.length; pre++) {
|
||||||
this.preDeployScripts.push(this.createFileProjectEntry(preDeploy[pre].getAttribute(constants.Include), EntryType.File));
|
this._preDeployScripts.push(this.createFileProjectEntry(preDeploy[pre].getAttribute(constants.Include), EntryType.File));
|
||||||
preDeployScriptCount++;
|
preDeployScriptCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +145,7 @@ export class Project {
|
|||||||
let postDeployScriptCount: number = 0;
|
let postDeployScriptCount: number = 0;
|
||||||
const postDeploy = itemGroup.getElementsByTagName(constants.PostDeploy);
|
const postDeploy = itemGroup.getElementsByTagName(constants.PostDeploy);
|
||||||
for (let post = 0; post < postDeploy.length; post++) {
|
for (let post = 0; post < postDeploy.length; post++) {
|
||||||
this.postDeployScripts.push(this.createFileProjectEntry(postDeploy[post].getAttribute(constants.Include), EntryType.File));
|
this._postDeployScripts.push(this.createFileProjectEntry(postDeploy[post].getAttribute(constants.Include), EntryType.File));
|
||||||
postDeployScriptCount++;
|
postDeployScriptCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +156,7 @@ export class Project {
|
|||||||
// find all none-deployment scripts to include
|
// find all none-deployment scripts to include
|
||||||
const noneItems = itemGroup.getElementsByTagName(constants.None);
|
const noneItems = itemGroup.getElementsByTagName(constants.None);
|
||||||
for (let n = 0; n < noneItems.length; n++) {
|
for (let n = 0; n < noneItems.length; n++) {
|
||||||
this.noneDeployScripts.push(this.createFileProjectEntry(noneItems[n].getAttribute(constants.Include), EntryType.File));
|
this._noneDeployScripts.push(this.createFileProjectEntry(noneItems[n].getAttribute(constants.Include), EntryType.File));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,11 +164,11 @@ export class Project {
|
|||||||
const importElements = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Import);
|
const importElements = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Import);
|
||||||
for (let i = 0; i < importElements.length; i++) {
|
for (let i = 0; i < importElements.length; i++) {
|
||||||
const importTarget = importElements[i];
|
const importTarget = importElements[i];
|
||||||
this.importedTargets.push(importTarget.getAttribute(constants.Project));
|
this._importedTargets.push(importTarget.getAttribute(constants.Project));
|
||||||
}
|
}
|
||||||
|
|
||||||
// find all SQLCMD variables to include
|
// find all SQLCMD variables to include
|
||||||
this.sqlCmdVariables = utils.readSqlCmdVariables(this.projFileXmlDoc);
|
this._sqlCmdVariables = utils.readSqlCmdVariables(this.projFileXmlDoc);
|
||||||
|
|
||||||
// find all database references to include
|
// find all database references to include
|
||||||
const references = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ArtifactReference);
|
const references = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ArtifactReference);
|
||||||
@@ -142,13 +187,13 @@ export class Project {
|
|||||||
|
|
||||||
const path = utils.convertSlashesForSqlProj(this.getSystemDacpacUri(`${name}.dacpac`).fsPath);
|
const path = utils.convertSlashesForSqlProj(this.getSystemDacpacUri(`${name}.dacpac`).fsPath);
|
||||||
if (path.includes(filepath)) {
|
if (path.includes(filepath)) {
|
||||||
this.databaseReferences.push(new SystemDatabaseReferenceProjectEntry(
|
this._databaseReferences.push(new SystemDatabaseReferenceProjectEntry(
|
||||||
Uri.file(filepath),
|
Uri.file(filepath),
|
||||||
this.getSystemDacpacSsdtUri(`${name}.dacpac`),
|
this.getSystemDacpacSsdtUri(`${name}.dacpac`),
|
||||||
name,
|
name,
|
||||||
suppressMissingDependencies));
|
suppressMissingDependencies));
|
||||||
} else {
|
} else {
|
||||||
this.databaseReferences.push(new DacpacReferenceProjectEntry({
|
this._databaseReferences.push(new DacpacReferenceProjectEntry({
|
||||||
dacpacFileLocation: Uri.file(utils.getPlatformSafeFileEntryPath(filepath)),
|
dacpacFileLocation: Uri.file(utils.getPlatformSafeFileEntryPath(filepath)),
|
||||||
databaseName: name,
|
databaseName: name,
|
||||||
suppressMissingDependenciesErrors: suppressMissingDependencies
|
suppressMissingDependenciesErrors: suppressMissingDependencies
|
||||||
@@ -171,7 +216,7 @@ export class Project {
|
|||||||
const suppressMissingDependenciesErrorNode = projectReferences[r].getElementsByTagName(constants.SuppressMissingDependenciesErrors);
|
const suppressMissingDependenciesErrorNode = projectReferences[r].getElementsByTagName(constants.SuppressMissingDependenciesErrors);
|
||||||
const suppressMissingDependencies = suppressMissingDependenciesErrorNode[0].childNodes[0].nodeValue === true ?? false;
|
const suppressMissingDependencies = suppressMissingDependenciesErrorNode[0].childNodes[0].nodeValue === true ?? false;
|
||||||
|
|
||||||
this.databaseReferences.push(new SqlProjectReferenceProjectEntry({
|
this._databaseReferences.push(new SqlProjectReferenceProjectEntry({
|
||||||
projectRelativePath: Uri.file(utils.getPlatformSafeFileEntryPath(filepath)),
|
projectRelativePath: Uri.file(utils.getPlatformSafeFileEntryPath(filepath)),
|
||||||
projectName: name,
|
projectName: name,
|
||||||
projectGuid: '', // don't care when just reading project as a reference
|
projectGuid: '', // don't care when just reading project as a reference
|
||||||
@@ -181,27 +226,27 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private resetProject(): void {
|
private resetProject(): void {
|
||||||
this.files = [];
|
this._files = [];
|
||||||
this.importedTargets = [];
|
this._importedTargets = [];
|
||||||
this.databaseReferences = [];
|
this._databaseReferences = [];
|
||||||
this.sqlCmdVariables = {};
|
this._sqlCmdVariables = {};
|
||||||
this.preDeployScripts = [];
|
this._preDeployScripts = [];
|
||||||
this.postDeployScripts = [];
|
this._postDeployScripts = [];
|
||||||
this.noneDeployScripts = [];
|
this._noneDeployScripts = [];
|
||||||
this.projFileXmlDoc = undefined;
|
this.projFileXmlDoc = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateProjectForRoundTrip(): Promise<void> {
|
public async updateProjectForRoundTrip(): Promise<void> {
|
||||||
if (this.importedTargets.includes(constants.NetCoreTargets) && !this.containsSSDTOnlySystemDatabaseReferences()) {
|
if (this._importedTargets.includes(constants.NetCoreTargets) && !this.containsSSDTOnlySystemDatabaseReferences()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TelemetryReporter.sendActionEvent(TelemetryViews.ProjectController, TelemetryActions.updateProjectForRoundtrip);
|
TelemetryReporter.sendActionEvent(TelemetryViews.ProjectController, TelemetryActions.updateProjectForRoundtrip);
|
||||||
|
|
||||||
if (!this.importedTargets.includes(constants.NetCoreTargets)) {
|
if (!this._importedTargets.includes(constants.NetCoreTargets)) {
|
||||||
const result = await window.showWarningMessage(constants.updateProjectForRoundTrip, constants.yesString, constants.noString);
|
const result = await window.showWarningMessage(constants.updateProjectForRoundTrip, constants.yesString, constants.noString);
|
||||||
if (result === constants.yesString) {
|
if (result === constants.yesString) {
|
||||||
await fs.copyFile(this.projectFilePath, this.projectFilePath + '_backup');
|
await fs.copyFile(this._projectFilePath, this._projectFilePath + '_backup');
|
||||||
await this.updateImportToSupportRoundTrip();
|
await this.updateImportToSupportRoundTrip();
|
||||||
await this.updatePackageReferenceInProjFile();
|
await this.updatePackageReferenceInProjFile();
|
||||||
await this.updateBeforeBuildTargetInProjFile();
|
await this.updateBeforeBuildTargetInProjFile();
|
||||||
@@ -210,7 +255,7 @@ export class Project {
|
|||||||
} else if (this.containsSSDTOnlySystemDatabaseReferences()) {
|
} else if (this.containsSSDTOnlySystemDatabaseReferences()) {
|
||||||
const result = await window.showWarningMessage(constants.updateProjectDatabaseReferencesForRoundTrip, constants.yesString, constants.noString);
|
const result = await window.showWarningMessage(constants.updateProjectDatabaseReferencesForRoundTrip, constants.yesString, constants.noString);
|
||||||
if (result === constants.yesString) {
|
if (result === constants.yesString) {
|
||||||
await fs.copyFile(this.projectFilePath, this.projectFilePath + '_backup');
|
await fs.copyFile(this._projectFilePath, this._projectFilePath + '_backup');
|
||||||
await this.updateSystemDatabaseReferencesInProjFile();
|
await this.updateSystemDatabaseReferencesInProjFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,7 +323,7 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const folderEntry = this.createFileProjectEntry(relativeFolderPath, EntryType.Folder);
|
const folderEntry = this.createFileProjectEntry(relativeFolderPath, EntryType.Folder);
|
||||||
this.files.push(folderEntry);
|
this._files.push(folderEntry);
|
||||||
|
|
||||||
await this.addToProjFile(folderEntry);
|
await this.addToProjFile(folderEntry);
|
||||||
return folderEntry;
|
return folderEntry;
|
||||||
@@ -321,15 +366,15 @@ export class Project {
|
|||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case templates.preDeployScript:
|
case templates.preDeployScript:
|
||||||
xmlTag = constants.PreDeploy;
|
xmlTag = constants.PreDeploy;
|
||||||
this.preDeployScripts.length === 0 ? this.preDeployScripts.push(fileEntry) : this.noneDeployScripts.push(fileEntry);
|
this._preDeployScripts.length === 0 ? this._preDeployScripts.push(fileEntry) : this._noneDeployScripts.push(fileEntry);
|
||||||
break;
|
break;
|
||||||
case templates.postDeployScript:
|
case templates.postDeployScript:
|
||||||
xmlTag = constants.PostDeploy;
|
xmlTag = constants.PostDeploy;
|
||||||
this.postDeployScripts.length === 0 ? this.postDeployScripts.push(fileEntry) : this.noneDeployScripts.push(fileEntry);
|
this._postDeployScripts.length === 0 ? this._postDeployScripts.push(fileEntry) : this._noneDeployScripts.push(fileEntry);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
xmlTag = constants.Build;
|
xmlTag = constants.Build;
|
||||||
this.files.push(fileEntry);
|
this._files.push(fileEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const attributes = new Map<string, string>();
|
const attributes = new Map<string, string>();
|
||||||
@@ -345,19 +390,19 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async exclude(entry: FileProjectEntry): Promise<void> {
|
public async exclude(entry: FileProjectEntry): Promise<void> {
|
||||||
const toExclude: FileProjectEntry[] = this.files.concat(this.preDeployScripts).concat(this.postDeployScripts).concat(this.noneDeployScripts).filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
const toExclude: FileProjectEntry[] = this._files.concat(this._preDeployScripts).concat(this._postDeployScripts).concat(this._noneDeployScripts).filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
await this.removeFromProjFile(toExclude);
|
await this.removeFromProjFile(toExclude);
|
||||||
|
|
||||||
this.files = this.files.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
this._files = this._files.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
this.preDeployScripts = this.preDeployScripts.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
this._preDeployScripts = this._preDeployScripts.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
this.postDeployScripts = this.postDeployScripts.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
this._postDeployScripts = this._postDeployScripts.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
this.noneDeployScripts = this.noneDeployScripts.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
this._noneDeployScripts = this._noneDeployScripts.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteFileFolder(entry: FileProjectEntry): Promise<void> {
|
public async deleteFileFolder(entry: FileProjectEntry): Promise<void> {
|
||||||
// compile a list of folder contents to delete; if entry is a file, contents will contain only itself
|
// compile a list of folder contents to delete; if entry is a file, contents will contain only itself
|
||||||
const toDeleteFiles: FileProjectEntry[] = this.files.concat(this.preDeployScripts).concat(this.postDeployScripts).concat(this.noneDeployScripts).filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File);
|
const toDeleteFiles: FileProjectEntry[] = this._files.concat(this._preDeployScripts).concat(this._postDeployScripts).concat(this._noneDeployScripts).filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File);
|
||||||
const toDeleteFolders: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder);
|
const toDeleteFolders: FileProjectEntry[] = this._files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder);
|
||||||
|
|
||||||
await Promise.all(toDeleteFiles.map(x => fs.unlink(x.fsUri.fsPath)));
|
await Promise.all(toDeleteFiles.map(x => fs.unlink(x.fsUri.fsPath)));
|
||||||
await Promise.all(toDeleteFolders.map(x => fs.rmdir(x.fsUri.fsPath, { recursive: true })));
|
await Promise.all(toDeleteFolders.map(x => fs.rmdir(x.fsUri.fsPath, { recursive: true })));
|
||||||
@@ -367,7 +412,7 @@ export class Project {
|
|||||||
|
|
||||||
public async deleteDatabaseReference(entry: IDatabaseReferenceProjectEntry): Promise<void> {
|
public async deleteDatabaseReference(entry: IDatabaseReferenceProjectEntry): Promise<void> {
|
||||||
await this.removeFromProjFile(entry);
|
await this.removeFromProjFile(entry);
|
||||||
this.databaseReferences = this.databaseReferences.filter(x => x !== entry);
|
this._databaseReferences = this._databaseReferences.filter(x => x !== entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -381,7 +426,7 @@ export class Project {
|
|||||||
this.projFileXmlDoc.getElementsByTagName(constants.DSP)[0].childNodes[0].nodeValue = newDSP;
|
this.projFileXmlDoc.getElementsByTagName(constants.DSP)[0].childNodes[0].nodeValue = newDSP;
|
||||||
|
|
||||||
// update any system db references
|
// update any system db references
|
||||||
const systemDbReferences = this.databaseReferences.filter(r => r instanceof SystemDatabaseReferenceProjectEntry) as SystemDatabaseReferenceProjectEntry[];
|
const systemDbReferences = this._databaseReferences.filter(r => r instanceof SystemDatabaseReferenceProjectEntry) as SystemDatabaseReferenceProjectEntry[];
|
||||||
if (systemDbReferences.length > 0) {
|
if (systemDbReferences.length > 0) {
|
||||||
for (let r of systemDbReferences) {
|
for (let r of systemDbReferences) {
|
||||||
// remove old entry in sqlproj
|
// remove old entry in sqlproj
|
||||||
@@ -686,12 +731,12 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.databaseReferenceExists(entry)) {
|
if (!this.databaseReferenceExists(entry)) {
|
||||||
this.databaseReferences.push(entry);
|
this._databaseReferences.push(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private databaseReferenceExists(entry: IDatabaseReferenceProjectEntry): boolean {
|
private databaseReferenceExists(entry: IDatabaseReferenceProjectEntry): boolean {
|
||||||
const found = this.databaseReferences.find(reference => reference.pathForSqlProj() === entry.pathForSqlProj()) !== undefined;
|
const found = this._databaseReferences.find(reference => reference.pathForSqlProj() === entry.pathForSqlProj()) !== undefined;
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,7 +794,7 @@ export class Project {
|
|||||||
|
|
||||||
public async addSqlCmdVariableToProjFile(entry: SqlCmdVariableProjectEntry): Promise<void> {
|
public async addSqlCmdVariableToProjFile(entry: SqlCmdVariableProjectEntry): Promise<void> {
|
||||||
// Remove any entries with the same variable name. It'll be replaced with a new one
|
// Remove any entries with the same variable name. It'll be replaced with a new one
|
||||||
if (Object.keys(this.sqlCmdVariables).includes(entry.variableName)) {
|
if (Object.keys(this._sqlCmdVariables).includes(entry.variableName)) {
|
||||||
await this.removeFromProjFile(entry);
|
await this.removeFromProjFile(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -759,7 +804,7 @@ export class Project {
|
|||||||
this.findOrCreateItemGroup(constants.SqlCmdVariable).appendChild(sqlCmdVariableNode);
|
this.findOrCreateItemGroup(constants.SqlCmdVariable).appendChild(sqlCmdVariableNode);
|
||||||
|
|
||||||
// add to the project's loaded sqlcmd variables
|
// add to the project's loaded sqlcmd variables
|
||||||
this.sqlCmdVariables[entry.variableName] = <string>entry.defaultValue;
|
this._sqlCmdVariables[entry.variableName] = <string>entry.defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private addSqlCmdVariableChildren(sqlCmdVariableNode: any, entry: SqlCmdVariableProjectEntry): void {
|
private addSqlCmdVariableChildren(sqlCmdVariableNode: any, entry: SqlCmdVariableProjectEntry): void {
|
||||||
@@ -807,7 +852,7 @@ export class Project {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.projFileXmlDoc.documentElement.appendChild(importNode, oldImportNode);
|
this.projFileXmlDoc.documentElement.appendChild(importNode, oldImportNode);
|
||||||
this.importedTargets.push(projectAttributeVal); // Add new import target to the list
|
this._importedTargets.push(projectAttributeVal); // Add new import target to the list
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.serializeToProjFile(this.projFileXmlDoc);
|
await this.serializeToProjFile(this.projFileXmlDoc);
|
||||||
@@ -866,7 +911,7 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove from database references because it'll get added again later
|
// remove from database references because it'll get added again later
|
||||||
this.databaseReferences.splice(this.databaseReferences.findIndex(n => n.databaseName === (systemDb === SystemDatabase.master ? constants.master : constants.msdb)), 1);
|
this._databaseReferences.splice(this._databaseReferences.findIndex(n => n.databaseName === (systemDb === SystemDatabase.master ? constants.master : constants.msdb)), 1);
|
||||||
|
|
||||||
await this.addSystemDatabaseReference({ databaseName: databaseVariableName, systemDb: systemDb, suppressMissingDependenciesErrors: suppressMissingDependences });
|
await this.addSystemDatabaseReference({ databaseName: databaseVariableName, systemDb: systemDb, suppressMissingDependenciesErrors: suppressMissingDependences });
|
||||||
}
|
}
|
||||||
@@ -930,7 +975,7 @@ export class Project {
|
|||||||
whiteSpaceAtEndOfSelfclosingTag: true
|
whiteSpaceAtEndOfSelfclosingTag: true
|
||||||
}); // TODO: replace <any>
|
}); // TODO: replace <any>
|
||||||
|
|
||||||
await fs.writeFile(this.projectFilePath, xml);
|
await fs.writeFile(this._projectFilePath, xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -948,7 +993,7 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let file of list) {
|
for (let file of list) {
|
||||||
const relativePath = utils.trimChars(utils.trimUri(Uri.file(this.projectFilePath), file), '/');
|
const relativePath = utils.trimChars(utils.trimUri(Uri.file(this._projectFilePath), file), '/');
|
||||||
|
|
||||||
if (relativePath.length > 0) {
|
if (relativePath.length > 0) {
|
||||||
const fileStat = await fs.stat(file.fsPath);
|
const fileStat = await fs.stat(file.fsPath);
|
||||||
@@ -974,7 +1019,7 @@ export abstract class ProjectEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FileProjectEntry extends ProjectEntry {
|
export class FileProjectEntry extends ProjectEntry implements IFileProjectEntry {
|
||||||
/**
|
/**
|
||||||
* Absolute file system URI
|
* Absolute file system URI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -77,6 +77,13 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
|
|||||||
return vscode.Uri.file(projectFile);
|
return vscode.Uri.file(projectFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens and loads a .sqlproj file
|
||||||
|
*/
|
||||||
|
openProject(projectFilePath: string): Promise<sqldbproj.ISqlProject> {
|
||||||
|
return Project.openProject(projectFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the supported project types
|
* Gets the supported project types
|
||||||
*/
|
*/
|
||||||
@@ -116,15 +123,6 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
|
|||||||
return [group, changeTargetPlatformAction];
|
return [group, changeTargetPlatformAction];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds the list of files and directories to the project, and saves the project file
|
|
||||||
* @param projectFile The Uri of the project file
|
|
||||||
* @param list list of uris of files and folders to add. Files and folders must already exist. Files and folders must already exist. No files or folders will be added if any do not exist.
|
|
||||||
*/
|
|
||||||
async addToProject(projectFile: vscode.Uri, list: vscode.Uri[]): Promise<void> {
|
|
||||||
const project = await Project.openProject(projectFile.fsPath);
|
|
||||||
await project.addToProject(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data to be displayed in the project dashboard
|
* Gets the data to be displayed in the project dashboard
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,10 +23,96 @@ declare module 'sqldbproj' {
|
|||||||
createProject(name: string, location: vscode.Uri, projectTypeId: string): Promise<vscode.Uri>;
|
createProject(name: string, location: vscode.Uri, projectTypeId: string): Promise<vscode.Uri>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the list of files and directories to the project, and saves the project file
|
* Opens and loads a .sqlproj file
|
||||||
* @param projectFile The Uri of the project file
|
*/
|
||||||
* @param list list of uris of files and folders to add. Files and folders must already exist. No files or folders will be added if any do not exist.
|
openProject(projectFilePath: string): Promise<ISqlProject>;
|
||||||
*/
|
}
|
||||||
addToProject(projectFile: vscode.Uri, list: vscode.Uri[]): Promise<void>;
|
|
||||||
|
export interface ISqlProject {
|
||||||
|
/**
|
||||||
|
* Reads the project setting and contents from the file
|
||||||
|
*/
|
||||||
|
readProjFile(): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the list of sql files and directories to the project, and saves the project file
|
||||||
|
* @param list list of files and folder Uris. Files and folders must already exist. No files or folders will be added if any do not exist.
|
||||||
|
*/
|
||||||
|
addToProject(list: vscode.Uri[]): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a folder to the project, and saves the project file
|
||||||
|
* @param relativeFolderPath Relative path of the folder
|
||||||
|
*/
|
||||||
|
addFolderItem(relativeFolderPath: string): Promise<IFileProjectEntry>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a file to disk if contents are provided, 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
|
||||||
|
*/
|
||||||
|
addScriptItem(relativeFilePath: string, contents?: string, itemType?: string): Promise<IFileProjectEntry>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a SQLCMD variable to the project
|
||||||
|
* @param name name of the variable
|
||||||
|
* @param defaultValue
|
||||||
|
*/
|
||||||
|
addSqlCmdVariable(name: string, defaultValue: string): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes entry from project by removing it from the project file
|
||||||
|
* @param entry
|
||||||
|
*/
|
||||||
|
exclude(entry: IFileProjectEntry): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes file or folder and removes it from the project file
|
||||||
|
* @param entry
|
||||||
|
*/
|
||||||
|
deleteFileFolder(entry: IFileProjectEntry): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the sql version the project is targeting
|
||||||
|
*/
|
||||||
|
getProjectTargetVersion(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path where dacpac is output to after a successful build
|
||||||
|
*/
|
||||||
|
readonly dacpacOutputPath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to folder containing the project file
|
||||||
|
*/
|
||||||
|
readonly projectFolderPath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project file path
|
||||||
|
*/
|
||||||
|
readonly projectFilePath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project file name
|
||||||
|
*/
|
||||||
|
readonly projectFileName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Files and folders that are included in the project
|
||||||
|
*/
|
||||||
|
readonly files: IFileProjectEntry[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SqlCmd variables and their values
|
||||||
|
*/
|
||||||
|
readonly sqlCmdVariables: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an entry in a project file
|
||||||
|
*/
|
||||||
|
export interface IFileProjectEntry {
|
||||||
|
fsUri: vscode.Uri;
|
||||||
|
relativePath: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user