mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-21 02:51:37 -05:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31bee67f00 | ||
|
|
e2949d4494 | ||
|
|
b6bd726066 | ||
|
|
0fe638974d | ||
|
|
f364e52079 | ||
|
|
84143d3caf | ||
|
|
0cfaf69647 | ||
|
|
343d878457 | ||
|
|
7d0cfc4f99 | ||
|
|
f13406570e | ||
|
|
c44ecf56f2 | ||
|
|
f10fc9b56d | ||
|
|
72acd2af83 | ||
|
|
6112eabc3c | ||
|
|
27bac701bb | ||
|
|
0bcd010d9a | ||
|
|
bca671bc3f | ||
|
|
706ba6c974 | ||
|
|
8e38295691 | ||
|
|
a97d882e3c |
@@ -4,6 +4,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.OctoKitIssue = exports.OctoKit = void 0;
|
||||||
const core_1 = require("@actions/core");
|
const core_1 = require("@actions/core");
|
||||||
const github_1 = require("@actions/github");
|
const github_1 = require("@actions/github");
|
||||||
const child_process_1 = require("child_process");
|
const child_process_1 = require("child_process");
|
||||||
@@ -20,7 +21,6 @@ class OctoKit {
|
|||||||
}
|
}
|
||||||
async *query(query) {
|
async *query(query) {
|
||||||
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`;
|
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`;
|
||||||
console.log(`Querying for ${q}:`);
|
|
||||||
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
|
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
|
||||||
...query,
|
...query,
|
||||||
q,
|
q,
|
||||||
@@ -41,19 +41,17 @@ class OctoKit {
|
|||||||
};
|
};
|
||||||
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
|
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
|
||||||
await timeout();
|
await timeout();
|
||||||
await utils_1.logRateLimit(this.token);
|
await (0, utils_1.logRateLimit)(this.token);
|
||||||
const page = pageResponse.data;
|
const page = pageResponse.data;
|
||||||
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`);
|
|
||||||
yield page.map((issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)));
|
yield page.map((issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async createIssue(owner, repo, title, body) {
|
async createIssue(owner, repo, title, body) {
|
||||||
core_1.debug(`Creating issue \`${title}\` on ${owner}/${repo}`);
|
(0, core_1.debug)(`Creating issue \`${title}\` on ${owner}/${repo}`);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.create({ owner, repo, title, body });
|
await this.octokit.issues.create({ owner, repo, title, body });
|
||||||
}
|
}
|
||||||
octokitIssueToIssue(issue) {
|
octokitIssueToIssue(issue) {
|
||||||
var _a, _b, _c, _d, _e, _f;
|
|
||||||
return {
|
return {
|
||||||
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
|
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
|
||||||
body: issue.body,
|
body: issue.body,
|
||||||
@@ -64,8 +62,8 @@ class OctoKit {
|
|||||||
locked: issue.locked,
|
locked: issue.locked,
|
||||||
numComments: issue.comments,
|
numComments: issue.comments,
|
||||||
reactions: issue.reactions,
|
reactions: issue.reactions,
|
||||||
assignee: (_b = (_a = issue.assignee) === null || _a === void 0 ? void 0 : _a.login) !== null && _b !== void 0 ? _b : (_d = (_c = issue.assignees) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.login,
|
assignee: issue.assignee?.login ?? issue.assignees?.[0]?.login,
|
||||||
milestoneId: (_f = (_e = issue.milestone) === null || _e === void 0 ? void 0 : _e.number) !== null && _f !== void 0 ? _f : null,
|
milestoneId: issue.milestone?.number ?? null,
|
||||||
createdAt: +new Date(issue.created_at),
|
createdAt: +new Date(issue.created_at),
|
||||||
updatedAt: +new Date(issue.updated_at),
|
updatedAt: +new Date(issue.updated_at),
|
||||||
closedAt: issue.closed_at ? +new Date(issue.closed_at) : undefined,
|
closedAt: issue.closed_at ? +new Date(issue.closed_at) : undefined,
|
||||||
@@ -73,10 +71,10 @@ class OctoKit {
|
|||||||
}
|
}
|
||||||
async hasWriteAccess(user) {
|
async hasWriteAccess(user) {
|
||||||
if (user.name in this.writeAccessCache) {
|
if (user.name in this.writeAccessCache) {
|
||||||
core_1.debug('Got permissions from cache for ' + user);
|
(0, core_1.debug)('Got permissions from cache for ' + user);
|
||||||
return this.writeAccessCache[user.name];
|
return this.writeAccessCache[user.name];
|
||||||
}
|
}
|
||||||
core_1.debug('Fetching permissions for ' + user);
|
(0, core_1.debug)('Fetching permissions for ' + user);
|
||||||
const permissions = (await this.octokit.repos.getCollaboratorPermissionLevel({
|
const permissions = (await this.octokit.repos.getCollaboratorPermissionLevel({
|
||||||
...this.params,
|
...this.params,
|
||||||
username: user.name,
|
username: user.name,
|
||||||
@@ -96,14 +94,14 @@ class OctoKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async createLabel(name, color, description) {
|
async createLabel(name, color, description) {
|
||||||
core_1.debug('Creating label ' + name);
|
(0, core_1.debug)('Creating label ' + name);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.createLabel({ ...this.params, color, description, name });
|
await this.octokit.issues.createLabel({ ...this.params, color, description, name });
|
||||||
else
|
else
|
||||||
this.mockLabels.add(name);
|
this.mockLabels.add(name);
|
||||||
}
|
}
|
||||||
async deleteLabel(name) {
|
async deleteLabel(name) {
|
||||||
core_1.debug('Deleting label ' + name);
|
(0, core_1.debug)('Deleting label ' + name);
|
||||||
try {
|
try {
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.deleteLabel({ ...this.params, name });
|
await this.octokit.issues.deleteLabel({ ...this.params, name });
|
||||||
@@ -116,7 +114,7 @@ class OctoKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async readConfig(path) {
|
async readConfig(path) {
|
||||||
core_1.debug('Reading config at ' + path);
|
(0, core_1.debug)('Reading config at ' + path);
|
||||||
const repoPath = `.github/${path}.json`;
|
const repoPath = `.github/${path}.json`;
|
||||||
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data;
|
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data;
|
||||||
if ('type' in data && data.type === 'file') {
|
if ('type' in data && data.type === 'file') {
|
||||||
@@ -128,10 +126,10 @@ class OctoKit {
|
|||||||
throw Error('Found directory at config path when expecting file' + JSON.stringify(data));
|
throw Error('Found directory at config path when expecting file' + JSON.stringify(data));
|
||||||
}
|
}
|
||||||
async releaseContainsCommit(release, commit) {
|
async releaseContainsCommit(release, commit) {
|
||||||
if (utils_1.getInput('commitReleasedDebuggingOverride')) {
|
if ((0, utils_1.getInput)('commitReleasedDebuggingOverride')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => child_process_1.exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => !err || err.code === 1 ? resolve(!err) : reject(err)));
|
return new Promise((resolve, reject) => (0, child_process_1.exec)(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => !err || err.code === 1 ? resolve(!err) : reject(err)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.OctoKit = OctoKit;
|
exports.OctoKit = OctoKit;
|
||||||
@@ -142,7 +140,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
this.issueData = issueData;
|
this.issueData = issueData;
|
||||||
}
|
}
|
||||||
async addAssignee(assignee) {
|
async addAssignee(assignee) {
|
||||||
core_1.debug('Adding assignee ' + assignee + ' to ' + this.issueData.number);
|
(0, core_1.debug)('Adding assignee ' + assignee + ' to ' + this.issueData.number);
|
||||||
if (!this.options.readonly) {
|
if (!this.options.readonly) {
|
||||||
await this.octokit.issues.addAssignees({
|
await this.octokit.issues.addAssignees({
|
||||||
...this.params,
|
...this.params,
|
||||||
@@ -152,7 +150,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async closeIssue() {
|
async closeIssue() {
|
||||||
core_1.debug('Closing issue ' + this.issueData.number);
|
(0, core_1.debug)('Closing issue ' + this.issueData.number);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.update({
|
await this.octokit.issues.update({
|
||||||
...this.params,
|
...this.params,
|
||||||
@@ -161,16 +159,15 @@ class OctoKitIssue extends OctoKit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async lockIssue() {
|
async lockIssue() {
|
||||||
core_1.debug('Locking issue ' + this.issueData.number);
|
(0, core_1.debug)('Locking issue ' + this.issueData.number);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number });
|
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number });
|
||||||
}
|
}
|
||||||
async getIssue() {
|
async getIssue() {
|
||||||
if (isIssue(this.issueData)) {
|
if (isIssue(this.issueData)) {
|
||||||
core_1.debug('Got issue data from query result ' + this.issueData.number);
|
(0, core_1.debug)('Got issue data from query result ' + this.issueData.number);
|
||||||
return this.issueData;
|
return this.issueData;
|
||||||
}
|
}
|
||||||
console.log('Fetching issue ' + this.issueData.number);
|
|
||||||
const issue = (await this.octokit.issues.get({
|
const issue = (await this.octokit.issues.get({
|
||||||
...this.params,
|
...this.params,
|
||||||
issue_number: this.issueData.number,
|
issue_number: this.issueData.number,
|
||||||
@@ -179,7 +176,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
return (this.issueData = this.octokitIssueToIssue(issue));
|
return (this.issueData = this.octokitIssueToIssue(issue));
|
||||||
}
|
}
|
||||||
async postComment(body) {
|
async postComment(body) {
|
||||||
core_1.debug(`Posting comment ${body} on ${this.issueData.number}`);
|
(0, core_1.debug)(`Posting comment ${body} on ${this.issueData.number}`);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.createComment({
|
await this.octokit.issues.createComment({
|
||||||
...this.params,
|
...this.params,
|
||||||
@@ -188,7 +185,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async deleteComment(id) {
|
async deleteComment(id) {
|
||||||
core_1.debug(`Deleting comment ${id} on ${this.issueData.number}`);
|
(0, core_1.debug)(`Deleting comment ${id} on ${this.issueData.number}`);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.deleteComment({
|
await this.octokit.issues.deleteComment({
|
||||||
owner: this.params.owner,
|
owner: this.params.owner,
|
||||||
@@ -197,7 +194,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async setMilestone(milestoneId) {
|
async setMilestone(milestoneId) {
|
||||||
core_1.debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
|
(0, core_1.debug)(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.update({
|
await this.octokit.issues.update({
|
||||||
...this.params,
|
...this.params,
|
||||||
@@ -206,7 +203,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async *getComments(last) {
|
async *getComments(last) {
|
||||||
core_1.debug('Fetching comments for ' + this.issueData.number);
|
(0, core_1.debug)('Fetching comments for ' + this.issueData.number);
|
||||||
const response = this.octokit.paginate.iterator(this.octokit.issues.listComments.endpoint.merge({
|
const response = this.octokit.paginate.iterator(this.octokit.issues.listComments.endpoint.merge({
|
||||||
...this.params,
|
...this.params,
|
||||||
issue_number: this.issueData.number,
|
issue_number: this.issueData.number,
|
||||||
@@ -223,7 +220,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async addLabel(name) {
|
async addLabel(name) {
|
||||||
core_1.debug(`Adding label ${name} to ${this.issueData.number}`);
|
(0, core_1.debug)(`Adding label ${name} to ${this.issueData.number}`);
|
||||||
if (!(await this.repoHasLabel(name))) {
|
if (!(await this.repoHasLabel(name))) {
|
||||||
throw Error(`Action could not execute becuase label ${name} is not defined.`);
|
throw Error(`Action could not execute becuase label ${name} is not defined.`);
|
||||||
}
|
}
|
||||||
@@ -235,7 +232,7 @@ class OctoKitIssue extends OctoKit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async removeLabel(name) {
|
async removeLabel(name) {
|
||||||
core_1.debug(`Removing label ${name} from ${this.issueData.number}`);
|
(0, core_1.debug)(`Removing label ${name} from ${this.issueData.number}`);
|
||||||
try {
|
try {
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
await this.octokit.issues.removeLabel({
|
await this.octokit.issues.removeLabel({
|
||||||
@@ -246,14 +243,12 @@ class OctoKitIssue extends OctoKit {
|
|||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (err.status === 404) {
|
if (err.status === 404) {
|
||||||
console.log(`Label ${name} not found on issue`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getClosingInfo() {
|
async getClosingInfo() {
|
||||||
var _a;
|
|
||||||
if ((await this.getIssue()).open) {
|
if ((await this.getIssue()).open) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -267,13 +262,12 @@ class OctoKitIssue extends OctoKit {
|
|||||||
for (const timelineEvent of timelineEvents) {
|
for (const timelineEvent of timelineEvents) {
|
||||||
if (timelineEvent.event === 'closed') {
|
if (timelineEvent.event === 'closed') {
|
||||||
closingCommit = {
|
closingCommit = {
|
||||||
hash: (_a = timelineEvent.commit_id) !== null && _a !== void 0 ? _a : undefined,
|
hash: timelineEvent.commit_id ?? undefined,
|
||||||
timestamp: +new Date(timelineEvent.created_at),
|
timestamp: +new Date(timelineEvent.created_at),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`Got ${closingCommit} as closing commit of ${this.issueData.number}`);
|
|
||||||
return closingCommit;
|
return closingCommit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export class OctoKit implements GitHub {
|
|||||||
|
|
||||||
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
|
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
|
||||||
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`
|
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`
|
||||||
console.log(`Querying for ${q}:`)
|
|
||||||
|
|
||||||
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
|
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
|
||||||
...query,
|
...query,
|
||||||
@@ -50,7 +49,6 @@ export class OctoKit implements GitHub {
|
|||||||
await timeout()
|
await timeout()
|
||||||
await logRateLimit(this.token)
|
await logRateLimit(this.token)
|
||||||
const page: Array<Octokit.SearchIssuesAndPullRequestsResponseItemsItem> = pageResponse.data
|
const page: Array<Octokit.SearchIssuesAndPullRequestsResponseItemsItem> = pageResponse.data
|
||||||
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`)
|
|
||||||
yield page.map(
|
yield page.map(
|
||||||
(issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)),
|
(issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)),
|
||||||
)
|
)
|
||||||
@@ -199,7 +197,6 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
|||||||
return this.issueData
|
return this.issueData
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Fetching issue ' + this.issueData.number)
|
|
||||||
const issue = (
|
const issue = (
|
||||||
await this.octokit.issues.get({
|
await this.octokit.issues.get({
|
||||||
...this.params,
|
...this.params,
|
||||||
@@ -286,7 +283,6 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.status === 404) {
|
if (err.status === 404) {
|
||||||
console.log(`Label ${name} not found on issue`)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw err
|
throw err
|
||||||
@@ -314,7 +310,6 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`Got ${closingCommit} as closing commit of ${this.issueData.number}`)
|
|
||||||
return closingCommit
|
return closingCommit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,17 +4,18 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.TestbedIssue = exports.Testbed = void 0;
|
||||||
class Testbed {
|
class Testbed {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
var _a, _b, _c, _d, _e;
|
|
||||||
this.config = {
|
this.config = {
|
||||||
globalLabels: (_a = config === null || config === void 0 ? void 0 : config.globalLabels) !== null && _a !== void 0 ? _a : [],
|
globalLabels: config?.globalLabels ?? [],
|
||||||
configs: (_b = config === null || config === void 0 ? void 0 : config.configs) !== null && _b !== void 0 ? _b : {},
|
configs: config?.configs ?? {},
|
||||||
writers: (_c = config === null || config === void 0 ? void 0 : config.writers) !== null && _c !== void 0 ? _c : [],
|
writers: config?.writers ?? [],
|
||||||
releasedCommits: (_d = config === null || config === void 0 ? void 0 : config.releasedCommits) !== null && _d !== void 0 ? _d : [],
|
releasedCommits: config?.releasedCommits ?? [],
|
||||||
queryRunner: (_e = config === null || config === void 0 ? void 0 : config.queryRunner) !== null && _e !== void 0 ? _e : async function* () {
|
queryRunner: config?.queryRunner ??
|
||||||
yield [];
|
async function* () {
|
||||||
},
|
yield [];
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async *query(query) {
|
async *query(query) {
|
||||||
@@ -47,16 +48,15 @@ class Testbed {
|
|||||||
exports.Testbed = Testbed;
|
exports.Testbed = Testbed;
|
||||||
class TestbedIssue extends Testbed {
|
class TestbedIssue extends Testbed {
|
||||||
constructor(globalConfig, issueConfig) {
|
constructor(globalConfig, issueConfig) {
|
||||||
var _a, _b, _c;
|
|
||||||
super(globalConfig);
|
super(globalConfig);
|
||||||
issueConfig = issueConfig !== null && issueConfig !== void 0 ? issueConfig : {};
|
issueConfig = issueConfig ?? {};
|
||||||
issueConfig.comments = (_a = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.comments) !== null && _a !== void 0 ? _a : [];
|
issueConfig.comments = issueConfig?.comments ?? [];
|
||||||
issueConfig.labels = (_b = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.labels) !== null && _b !== void 0 ? _b : [];
|
issueConfig.labels = issueConfig?.labels ?? [];
|
||||||
issueConfig.issue = {
|
issueConfig.issue = {
|
||||||
author: { name: 'JacksonKearl' },
|
author: { name: 'JacksonKearl' },
|
||||||
body: 'issue body',
|
body: 'issue body',
|
||||||
locked: false,
|
locked: false,
|
||||||
numComments: ((_c = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.comments) === null || _c === void 0 ? void 0 : _c.length) || 0,
|
numComments: issueConfig?.comments?.length || 0,
|
||||||
number: 1,
|
number: 1,
|
||||||
open: true,
|
open: true,
|
||||||
title: 'issue title',
|
title: 'issue title',
|
||||||
@@ -90,7 +90,7 @@ class TestbedIssue extends Testbed {
|
|||||||
}
|
}
|
||||||
async postComment(body, author) {
|
async postComment(body, author) {
|
||||||
this.issueConfig.comments.push({
|
this.issueConfig.comments.push({
|
||||||
author: { name: author !== null && author !== void 0 ? author : 'bot' },
|
author: { name: author ?? 'bot' },
|
||||||
body,
|
body,
|
||||||
id: Math.random(),
|
id: Math.random(),
|
||||||
timestamp: +new Date(),
|
timestamp: +new Date(),
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ const core = require("@actions/core");
|
|||||||
const github_1 = require("@actions/github");
|
const github_1 = require("@actions/github");
|
||||||
const octokit_1 = require("../api/octokit");
|
const octokit_1 = require("../api/octokit");
|
||||||
const utils_1 = require("../utils/utils");
|
const utils_1 = require("../utils/utils");
|
||||||
const token = utils_1.getRequiredInput('token');
|
const token = (0, utils_1.getRequiredInput)('token');
|
||||||
const label = utils_1.getRequiredInput('label');
|
const label = (0, utils_1.getRequiredInput)('label');
|
||||||
async function main() {
|
async function main() {
|
||||||
const pr = new octokit_1.OctoKitIssue(token, github_1.context.repo, { number: github_1.context.issue.number });
|
const pr = new octokit_1.OctoKitIssue(token, github_1.context.repo, { number: github_1.context.issue.number });
|
||||||
pr.addLabel(label);
|
pr.addLabel(label);
|
||||||
}
|
}
|
||||||
main()
|
main()
|
||||||
.then(() => utils_1.logRateLimit(token))
|
.then(() => (0, utils_1.logRateLimit)(token))
|
||||||
.catch(async (error) => {
|
.catch(async (error) => {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
await utils_1.logErrorToIssue(error.message, true, token);
|
await (0, utils_1.logErrorToIssue)(error.message, true, token);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
{
|
{
|
||||||
"name": "github-actions",
|
"name": "github-actions",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "GitHub Actions",
|
"description": "GitHub Actions",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha -r ts-node/register **/*.test.ts",
|
"test": "mocha -r ts-node/register **/*.test.ts",
|
||||||
"build": "tsc -p ./tsconfig.json",
|
"build": "tsc -p ./tsconfig.json",
|
||||||
"lint": "eslint -c .eslintrc --fix --ext .ts .",
|
"compile": "tsc -p ./tsconfig.json",
|
||||||
"watch-typecheck": "tsc --watch"
|
"lint": "eslint -c .eslintrc --fix --ext .ts .",
|
||||||
},
|
"watch-typecheck": "tsc --watch"
|
||||||
"repository": {
|
},
|
||||||
"type": "git",
|
"repository": {
|
||||||
"url": "git+https://github.com/microsoft/azuredatastudio.git"
|
"type": "git",
|
||||||
},
|
"url": "git+https://github.com/microsoft/azuredatastudio.git"
|
||||||
"keywords": [],
|
},
|
||||||
"author": "",
|
"keywords": [],
|
||||||
"dependencies": {
|
"author": "",
|
||||||
"@actions/core": "^1.2.6",
|
"dependencies": {
|
||||||
"@actions/github": "^2.1.1",
|
"@actions/core": "^1.2.6",
|
||||||
"axios": "^0.21.4",
|
"@actions/github": "^2.1.1",
|
||||||
|
"axios": "^0.21.4",
|
||||||
"ts-node": "^8.6.2",
|
"ts-node": "^8.6.2",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,16 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.logErrorToIssue = exports.logRateLimit = exports.daysAgoToHumanReadbleDate = exports.daysAgoToTimestamp = exports.loadLatestRelease = exports.normalizeIssue = exports.getRequiredInput = exports.getInput = void 0;
|
||||||
const core = require("@actions/core");
|
const core = require("@actions/core");
|
||||||
const github_1 = require("@actions/github");
|
const github_1 = require("@actions/github");
|
||||||
const axios_1 = require("axios");
|
const axios_1 = require("axios");
|
||||||
const octokit_1 = require("../api/octokit");
|
const octokit_1 = require("../api/octokit");
|
||||||
exports.getInput = (name) => core.getInput(name) || undefined;
|
const getInput = (name) => core.getInput(name) || undefined;
|
||||||
exports.getRequiredInput = (name) => core.getInput(name, { required: true });
|
exports.getInput = getInput;
|
||||||
exports.normalizeIssue = (issue) => {
|
const getRequiredInput = (name) => core.getInput(name, { required: true });
|
||||||
|
exports.getRequiredInput = getRequiredInput;
|
||||||
|
const normalizeIssue = (issue) => {
|
||||||
const { body, title } = issue;
|
const { body, title } = issue;
|
||||||
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body);
|
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body);
|
||||||
const isFeatureRequest = body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body);
|
const isFeatureRequest = body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body);
|
||||||
@@ -33,23 +36,25 @@ exports.normalizeIssue = (issue) => {
|
|||||||
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
|
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
exports.loadLatestRelease = async (quality) => (await axios_1.default.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data;
|
exports.normalizeIssue = normalizeIssue;
|
||||||
exports.daysAgoToTimestamp = (days) => +new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
const loadLatestRelease = async (quality) => (await axios_1.default.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data;
|
||||||
exports.daysAgoToHumanReadbleDate = (days) => new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
|
exports.loadLatestRelease = loadLatestRelease;
|
||||||
exports.logRateLimit = async (token) => {
|
const daysAgoToTimestamp = (days) => +new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
||||||
|
exports.daysAgoToTimestamp = daysAgoToTimestamp;
|
||||||
|
const daysAgoToHumanReadbleDate = (days) => new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
|
||||||
|
exports.daysAgoToHumanReadbleDate = daysAgoToHumanReadbleDate;
|
||||||
|
const logRateLimit = async (token) => {
|
||||||
const usageData = (await new github_1.GitHub(token).rateLimit.get()).data.resources;
|
const usageData = (await new github_1.GitHub(token).rateLimit.get()).data.resources;
|
||||||
['core', 'graphql', 'search'].forEach(async (category) => {
|
['core', 'graphql', 'search'].forEach(async (category) => {
|
||||||
const usage = 1 - usageData[category].remaining / usageData[category].limit;
|
const usage = 1 - usageData[category].remaining / usageData[category].limit;
|
||||||
const message = `Usage at ${usage} for ${category}`;
|
const message = `Usage at ${usage} for ${category}`;
|
||||||
if (usage > 0) {
|
|
||||||
console.log(message);
|
|
||||||
}
|
|
||||||
if (usage > 0.5) {
|
if (usage > 0.5) {
|
||||||
await exports.logErrorToIssue(message, false, token);
|
await (0, exports.logErrorToIssue)(message, false, token);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.logErrorToIssue = async (message, ping, token) => {
|
exports.logRateLimit = logRateLimit;
|
||||||
|
const logErrorToIssue = async (message, ping, token) => {
|
||||||
// Attempt to wait out abuse detection timeout if present
|
// Attempt to wait out abuse detection timeout if present
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||||
const dest = github_1.context.repo.repo === 'vscode-internalbacklog'
|
const dest = github_1.context.repo.repo === 'vscode-internalbacklog'
|
||||||
@@ -70,3 +75,4 @@ ${JSON.stringify(github_1.context, null, 2).replace(/<!--/gu, '<@--').replace(/-
|
|||||||
-->
|
-->
|
||||||
`);
|
`);
|
||||||
};
|
};
|
||||||
|
exports.logErrorToIssue = logErrorToIssue;
|
||||||
|
|||||||
@@ -58,13 +58,10 @@ export const daysAgoToHumanReadbleDate = (days: number) =>
|
|||||||
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '')
|
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '')
|
||||||
|
|
||||||
export const logRateLimit = async (token: string) => {
|
export const logRateLimit = async (token: string) => {
|
||||||
const usageData = (await new GitHub(token).rateLimit.get()).data.resources
|
const usageData = (await new GitHub(token).rateLimit.get()).data.resources;
|
||||||
;(['core', 'graphql', 'search'] as const).forEach(async (category) => {
|
(['core', 'graphql', 'search'] as const).forEach(async (category) => {
|
||||||
const usage = 1 - usageData[category].remaining / usageData[category].limit
|
const usage = 1 - usageData[category].remaining / usageData[category].limit
|
||||||
const message = `Usage at ${usage} for ${category}`
|
const message = `Usage at ${usage} for ${category}`
|
||||||
if (usage > 0) {
|
|
||||||
console.log(message)
|
|
||||||
}
|
|
||||||
if (usage > 0.5) {
|
if (usage > 0.5) {
|
||||||
await logErrorToIssue(message, false, token)
|
await logErrorToIssue(message, false, token)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,8 @@ node-fetch@^2.3.0:
|
|||||||
version "2.6.7"
|
version "2.6.7"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
||||||
|
dependencies:
|
||||||
|
whatwg-url "^5.0.0"
|
||||||
|
|
||||||
npm-run-path@^2.0.0:
|
npm-run-path@^2.0.0:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
@@ -371,6 +373,11 @@ strip-eof@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||||
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
|
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
|
||||||
|
|
||||||
|
tr46@~0.0.3:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
|
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||||
|
|
||||||
ts-node@^8.6.2:
|
ts-node@^8.6.2:
|
||||||
version "8.9.0"
|
version "8.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.0.tgz#d7bf7272dcbecd3a2aa18bd0b96c7d2f270c15d4"
|
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.0.tgz#d7bf7272dcbecd3a2aa18bd0b96c7d2f270c15d4"
|
||||||
@@ -388,9 +395,9 @@ tunnel@0.0.6, tunnel@^0.0.6:
|
|||||||
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
||||||
|
|
||||||
typescript@^3.8.3:
|
typescript@^3.8.3:
|
||||||
version "3.8.3"
|
version "3.9.10"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
|
||||||
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
|
integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
|
||||||
|
|
||||||
universal-user-agent@^4.0.0:
|
universal-user-agent@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
@@ -411,6 +418,19 @@ uuid@^8.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
|
webidl-conversions@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
|
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||||
|
|
||||||
|
whatwg-url@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||||
|
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
||||||
|
dependencies:
|
||||||
|
tr46 "~0.0.3"
|
||||||
|
webidl-conversions "^3.0.0"
|
||||||
|
|
||||||
which@^1.2.9:
|
which@^1.2.9:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ function getEnv(name) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
async function main() {
|
async function main() {
|
||||||
var _a;
|
|
||||||
const [, , product, os, arch, unprocessedType, fileName, filePath] = process.argv;
|
const [, , product, os, arch, unprocessedType, fileName, filePath] = process.argv;
|
||||||
// getPlatform needs the unprocessedType
|
// getPlatform needs the unprocessedType
|
||||||
const platform = getPlatform(product, os, arch, unprocessedType);
|
const platform = getPlatform(product, os, arch, unprocessedType);
|
||||||
@@ -169,7 +168,7 @@ async function main() {
|
|||||||
console.log('Blob successfully uploaded to Azure storage.');
|
console.log('Blob successfully uploaded to Azure storage.');
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
const shouldUploadToMooncake = /true/i.test((_a = process.env['VSCODE_PUBLISH_TO_MOONCAKE']) !== null && _a !== void 0 ? _a : 'true');
|
const shouldUploadToMooncake = /true/i.test(process.env['VSCODE_PUBLISH_TO_MOONCAKE'] ?? 'true');
|
||||||
if (shouldUploadToMooncake) {
|
if (shouldUploadToMooncake) {
|
||||||
const mooncakeCredential = new identity_1.ClientSecretCredential(process.env['AZURE_MOONCAKE_TENANT_ID'], process.env['AZURE_MOONCAKE_CLIENT_ID'], process.env['AZURE_MOONCAKE_CLIENT_SECRET']);
|
const mooncakeCredential = new identity_1.ClientSecretCredential(process.env['AZURE_MOONCAKE_TENANT_ID'], process.env['AZURE_MOONCAKE_CLIENT_ID'], process.env['AZURE_MOONCAKE_CLIENT_SECRET']);
|
||||||
const mooncakeBlobServiceClient = new storage_blob_1.BlobServiceClient(`https://vscode.blob.core.chinacloudapi.cn`, mooncakeCredential, storagePipelineOptions);
|
const mooncakeBlobServiceClient = new storage_blob_1.BlobServiceClient(`https://vscode.blob.core.chinacloudapi.cn`, mooncakeCredential, storagePipelineOptions);
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ function getEnv(name) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
async function main() {
|
async function main() {
|
||||||
var _a, _b, _c;
|
|
||||||
const [, , _version] = process.argv;
|
const [, , _version] = process.argv;
|
||||||
const quality = getEnv('VSCODE_QUALITY');
|
const quality = getEnv('VSCODE_QUALITY');
|
||||||
const commit = ((_a = process.env['VSCODE_DISTRO_COMMIT']) === null || _a === void 0 ? void 0 : _a.trim()) || getEnv('BUILD_SOURCEVERSION');
|
const commit = process.env['VSCODE_DISTRO_COMMIT']?.trim() || getEnv('BUILD_SOURCEVERSION');
|
||||||
const queuedBy = getEnv('BUILD_QUEUEDBY');
|
const queuedBy = getEnv('BUILD_QUEUEDBY');
|
||||||
const sourceBranch = ((_b = process.env['VSCODE_DISTRO_REF']) === null || _b === void 0 ? void 0 : _b.trim()) || getEnv('BUILD_SOURCEBRANCH');
|
const sourceBranch = process.env['VSCODE_DISTRO_REF']?.trim() || getEnv('BUILD_SOURCEBRANCH');
|
||||||
const version = _version + (quality === 'stable' ? '' : `-${quality}`);
|
const version = _version + (quality === 'stable' ? '' : `-${quality}`);
|
||||||
console.log('Creating build...');
|
console.log('Creating build...');
|
||||||
console.log('Quality:', quality);
|
console.log('Quality:', quality);
|
||||||
@@ -35,7 +34,7 @@ async function main() {
|
|||||||
timestamp: (new Date()).getTime(),
|
timestamp: (new Date()).getTime(),
|
||||||
version,
|
version,
|
||||||
isReleased: false,
|
isReleased: false,
|
||||||
private: Boolean((_c = process.env['VSCODE_DISTRO_REF']) === null || _c === void 0 ? void 0 : _c.trim()),
|
private: Boolean(process.env['VSCODE_DISTRO_REF']?.trim()),
|
||||||
sourceBranch,
|
sourceBranch,
|
||||||
queuedBy,
|
queuedBy,
|
||||||
assets: [],
|
assets: [],
|
||||||
@@ -44,7 +43,7 @@ async function main() {
|
|||||||
const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
|
const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
|
||||||
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
|
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
|
||||||
const scripts = client.database('builds').container(quality).scripts;
|
const scripts = client.database('builds').container(quality).scripts;
|
||||||
await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [Object.assign(Object.assign({}, build), { _partitionKey: '' })]));
|
await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
|
||||||
}
|
}
|
||||||
main().then(() => {
|
main().then(() => {
|
||||||
console.log('Build successfully created');
|
console.log('Build successfully created');
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ async function assertContainer(containerClient) {
|
|||||||
return containerResponse && !!containerResponse.errorCode;
|
return containerResponse && !!containerResponse.errorCode;
|
||||||
}
|
}
|
||||||
async function uploadBlob(blobClient, file) {
|
async function uploadBlob(blobClient, file) {
|
||||||
var _a, _b;
|
|
||||||
const result = await blobClient.uploadFile(file, {
|
const result = await blobClient.uploadFile(file, {
|
||||||
blobHTTPHeaders: {
|
blobHTTPHeaders: {
|
||||||
blobContentType: mime.lookup(file),
|
blobContentType: mime.lookup(file),
|
||||||
@@ -117,10 +116,10 @@ async function uploadBlob(blobClient, file) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result && !result.errorCode) {
|
if (result && !result.errorCode) {
|
||||||
console.log(`Blobs uploaded successfully, response status: ${(_a = result === null || result === void 0 ? void 0 : result._response) === null || _a === void 0 ? void 0 : _a.status}`);
|
console.log(`Blobs uploaded successfully, response status: ${result?._response?.status}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.error(`Blobs failed to upload, response status: ${(_b = result === null || result === void 0 ? void 0 : result._response) === null || _b === void 0 ? void 0 : _b.status}, errorcode: ${result === null || result === void 0 ? void 0 : result.errorCode}`);
|
console.error(`Blobs failed to upload, response status: ${result?._response?.status}, errorcode: ${result?.errorCode}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function publish(commit, quality, platform, type, name, version, _isUpdate, file, opts) {
|
async function publish(commit, quality, platform, type, name, version, _isUpdate, file, opts) {
|
||||||
|
|||||||
@@ -180,12 +180,11 @@ steps:
|
|||||||
# continueOnError: true
|
# continueOnError: true
|
||||||
# condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
|
# condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
|
||||||
|
|
||||||
# {{SQL CARBON TODO}} - Reenable
|
- script: |
|
||||||
# - script: |
|
set -e
|
||||||
# set -e
|
yarn gulp vscode-linux-x64-build-deb
|
||||||
# yarn gulp vscode-linux-x64-build-deb
|
displayName: Build Deb
|
||||||
# displayName: Build Deb
|
condition: and(succeeded(), ne(variables['EXTENSIONS_ONLY'], 'true'))
|
||||||
# condition: and(succeeded(), ne(variables['EXTENSIONS_ONLY'], 'true'))
|
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
|
|||||||
@@ -27,16 +27,16 @@ If (-NOT ($Quality -eq "stable")) {
|
|||||||
node $sourcesDir\build\azure-pipelines\common\publish.js $Quality $PlatformLinux archive-unsigned "$TarballUploadName.tar.gz" $Version true $TarballPath $CommitId
|
node $sourcesDir\build\azure-pipelines\common\publish.js $Quality $PlatformLinux archive-unsigned "$TarballUploadName.tar.gz" $Version true $TarballPath $CommitId
|
||||||
|
|
||||||
# Publish DEB
|
# Publish DEB
|
||||||
# $PlatformDeb = "linux-deb-$Arch"
|
$PlatformDeb = "linux-deb-$Arch"
|
||||||
# $DebFilename = "$(Get-ChildItem -File -Name $artifactsDir\linux\deb\amd64\deb\*.deb)"
|
$DebFilename = "$(Get-ChildItem -File -Name $artifactsDir\linux\deb\amd64\deb\*.deb)"
|
||||||
# $DebPath = "$artifactsDir\linux\deb\amd64\deb\$DebFilename"
|
$DebPath = "$artifactsDir\linux\deb\amd64\deb\$DebFilename"
|
||||||
# $DebUploadName = "azuredatastudio-linux-$Version"
|
$DebUploadName = "azuredatastudio-linux-$Version"
|
||||||
|
|
||||||
# If (-NOT ($Quality -eq "stable")) {
|
If (-NOT ($Quality -eq "stable")) {
|
||||||
# $DebUploadName = "$DebUploadName-$Quality"
|
$DebUploadName = "$DebUploadName-$Quality"
|
||||||
# }
|
}
|
||||||
|
|
||||||
# node $sourcesDir\build\azure-pipelines\common\publish.js $Quality $PlatformDeb package "$DebUploadName.deb" $Version true $DebPath $CommitId
|
node $sourcesDir\build\azure-pipelines\common\publish.js $Quality $PlatformDeb package "$DebUploadName.deb" $Version true $DebPath $CommitId
|
||||||
|
|
||||||
# Publish RPM
|
# Publish RPM
|
||||||
$PlatformRpm = "linux-rpm-$Arch"
|
$PlatformRpm = "linux-rpm-$Arch"
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ async function mixinClient(quality) {
|
|||||||
else {
|
else {
|
||||||
fancyLog(ansiColors.blue('[mixin]'), 'Inheriting OSS built-in extensions', builtInExtensions.map(e => e.name));
|
fancyLog(ansiColors.blue('[mixin]'), 'Inheriting OSS built-in extensions', builtInExtensions.map(e => e.name));
|
||||||
}
|
}
|
||||||
return Object.assign(Object.assign({ webBuiltInExtensions: originalProduct.webBuiltInExtensions }, o), { builtInExtensions });
|
return { webBuiltInExtensions: originalProduct.webBuiltInExtensions, ...o, builtInExtensions };
|
||||||
}))
|
}))
|
||||||
.pipe(productJsonFilter.restore)
|
.pipe(productJsonFilter.restore)
|
||||||
.pipe(es.mapSync((f) => {
|
.pipe(es.mapSync((f) => {
|
||||||
@@ -64,7 +64,7 @@ function mixinServer(quality) {
|
|||||||
fancyLog(ansiColors.blue('[mixin]'), `Mixing in server:`);
|
fancyLog(ansiColors.blue('[mixin]'), `Mixing in server:`);
|
||||||
const originalProduct = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'product.json'), 'utf8'));
|
const originalProduct = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'product.json'), 'utf8'));
|
||||||
const serverProductJson = JSON.parse(fs.readFileSync(serverProductJsonPath, 'utf8'));
|
const serverProductJson = JSON.parse(fs.readFileSync(serverProductJsonPath, 'utf8'));
|
||||||
fs.writeFileSync('product.json', JSON.stringify(Object.assign(Object.assign({}, originalProduct), serverProductJson), undefined, '\t'));
|
fs.writeFileSync('product.json', JSON.stringify({ ...originalProduct, ...serverProductJson }, undefined, '\t'));
|
||||||
fancyLog(ansiColors.blue('[mixin]'), 'product.json', ansiColors.green('✔︎'));
|
fancyLog(ansiColors.blue('[mixin]'), 'product.json', ansiColors.green('✔︎'));
|
||||||
}
|
}
|
||||||
function main() {
|
function main() {
|
||||||
|
|||||||
@@ -40,14 +40,26 @@ async function main() {
|
|||||||
identity: '99FM488X57',
|
identity: '99FM488X57',
|
||||||
'gatekeeper-assess': false
|
'gatekeeper-assess': false
|
||||||
};
|
};
|
||||||
const appOpts = Object.assign(Object.assign({}, defaultOpts), {
|
const appOpts = {
|
||||||
|
...defaultOpts,
|
||||||
// TODO(deepak1556): Incorrectly declared type in electron-osx-sign
|
// TODO(deepak1556): Incorrectly declared type in electron-osx-sign
|
||||||
ignore: (filePath) => {
|
ignore: (filePath) => {
|
||||||
return filePath.includes(gpuHelperAppName) ||
|
return filePath.includes(gpuHelperAppName) ||
|
||||||
filePath.includes(rendererHelperAppName);
|
filePath.includes(rendererHelperAppName);
|
||||||
} });
|
}
|
||||||
const gpuHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, gpuHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist') });
|
};
|
||||||
const rendererHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, rendererHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist') });
|
const gpuHelperOpts = {
|
||||||
|
...defaultOpts,
|
||||||
|
app: path.join(appFrameworkPath, gpuHelperAppName),
|
||||||
|
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'),
|
||||||
|
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'),
|
||||||
|
};
|
||||||
|
const rendererHelperOpts = {
|
||||||
|
...defaultOpts,
|
||||||
|
app: path.join(appFrameworkPath, rendererHelperAppName),
|
||||||
|
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'),
|
||||||
|
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'),
|
||||||
|
};
|
||||||
// Only overwrite plist entries for x64 and arm64 builds,
|
// Only overwrite plist entries for x64 and arm64 builds,
|
||||||
// universal will get its copy from the x64 build.
|
// universal will get its copy from the x64 build.
|
||||||
if (arch !== 'universal') {
|
if (arch !== 'universal') {
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "commonjs",
|
|
||||||
"target": "es2017",
|
|
||||||
"jsx": "preserve",
|
|
||||||
"checkJs": true
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"**/*.js"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"**/node_modules/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -45,8 +45,7 @@ function isUpToDate(extension) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function syncMarketplaceExtension(extension) {
|
function syncMarketplaceExtension(extension) {
|
||||||
var _a;
|
const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl;
|
||||||
const galleryServiceUrl = (_a = productjson.extensionsGallery) === null || _a === void 0 ? void 0 : _a.serviceUrl;
|
|
||||||
const source = ansiColors.blue(galleryServiceUrl ? '[marketplace]' : '[github]');
|
const source = ansiColors.blue(galleryServiceUrl ? '[marketplace]' : '[github]');
|
||||||
if (isUpToDate(extension)) {
|
if (isUpToDate(extension)) {
|
||||||
log(source, `${extension.name}@${extension.version}`, ansiColors.green('✔︎'));
|
log(source, `${extension.name}@${extension.version}`, ansiColors.green('✔︎'));
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const token = process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'
|
|||||||
const contentBasePath = 'raw.githubusercontent.com';
|
const contentBasePath = 'raw.githubusercontent.com';
|
||||||
const contentFileNames = ['package.json', 'package-lock.json', 'yarn.lock'];
|
const contentFileNames = ['package.json', 'package-lock.json', 'yarn.lock'];
|
||||||
async function downloadExtensionDetails(extension) {
|
async function downloadExtensionDetails(extension) {
|
||||||
var _a, _b, _c;
|
|
||||||
const extensionLabel = `${extension.name}@${extension.version}`;
|
const extensionLabel = `${extension.name}@${extension.version}`;
|
||||||
const repository = url.parse(extension.repo).path.substr(1);
|
const repository = url.parse(extension.repo).path.substr(1);
|
||||||
const repositoryContentBaseUrl = `https://${token ? `${token}@` : ''}${contentBasePath}/${repository}/v${extension.version}`;
|
const repositoryContentBaseUrl = `https://${token ? `${token}@` : ''}${contentBasePath}/${repository}/v${extension.version}`;
|
||||||
@@ -56,11 +55,11 @@ async function downloadExtensionDetails(extension) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Validation
|
// Validation
|
||||||
if (!((_a = results.find(r => r.fileName === 'package.json')) === null || _a === void 0 ? void 0 : _a.body)) {
|
if (!results.find(r => r.fileName === 'package.json')?.body) {
|
||||||
// throw new Error(`The "package.json" file could not be found for the built-in extension - ${extensionLabel}`);
|
// throw new Error(`The "package.json" file could not be found for the built-in extension - ${extensionLabel}`);
|
||||||
}
|
}
|
||||||
if (!((_b = results.find(r => r.fileName === 'package-lock.json')) === null || _b === void 0 ? void 0 : _b.body) &&
|
if (!results.find(r => r.fileName === 'package-lock.json')?.body &&
|
||||||
!((_c = results.find(r => r.fileName === 'yarn.lock')) === null || _c === void 0 ? void 0 : _c.body)) {
|
!results.find(r => r.fileName === 'yarn.lock')?.body) {
|
||||||
// throw new Error(`The "package-lock.json"/"yarn.lock" could not be found for the built-in extension - ${extensionLabel}`);
|
// throw new Error(`The "package-lock.json"/"yarn.lock" could not be found for the built-in extension - ${extensionLabel}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,12 +21,11 @@ function bundle(entryPoints, config, callback) {
|
|||||||
});
|
});
|
||||||
const allMentionedModulesMap = {};
|
const allMentionedModulesMap = {};
|
||||||
entryPoints.forEach((module) => {
|
entryPoints.forEach((module) => {
|
||||||
var _a, _b;
|
|
||||||
allMentionedModulesMap[module.name] = true;
|
allMentionedModulesMap[module.name] = true;
|
||||||
(_a = module.include) === null || _a === void 0 ? void 0 : _a.forEach(function (includedModule) {
|
module.include?.forEach(function (includedModule) {
|
||||||
allMentionedModulesMap[includedModule] = true;
|
allMentionedModulesMap[includedModule] = true;
|
||||||
});
|
});
|
||||||
(_b = module.exclude) === null || _b === void 0 ? void 0 : _b.forEach(function (excludedModule) {
|
module.exclude?.forEach(function (excludedModule) {
|
||||||
allMentionedModulesMap[excludedModule] = true;
|
allMentionedModulesMap[excludedModule] = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use strict";
|
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.watchApiProposalNamesTask = exports.compileApiProposalNamesTask = exports.watchTask = exports.compileTask = exports.transpileTask = void 0;
|
exports.watchApiProposalNamesTask = exports.compileApiProposalNamesTask = exports.watchTask = exports.compileTask = exports.transpileTask = void 0;
|
||||||
const es = require("event-stream");
|
const es = require("event-stream");
|
||||||
@@ -38,7 +38,7 @@ function createCompile(src, build, emitError, transpileOnly) {
|
|||||||
const tsb = require('./tsb');
|
const tsb = require('./tsb');
|
||||||
const sourcemaps = require('gulp-sourcemaps');
|
const sourcemaps = require('gulp-sourcemaps');
|
||||||
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
|
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
|
||||||
const overrideOptions = Object.assign(Object.assign({}, getTypeScriptCompilerOptions(src)), { inlineSources: Boolean(build) });
|
const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) };
|
||||||
// {{SQL CARBON EDIT}} Add override for not inlining the sourcemap during build so we can get code coverage - it
|
// {{SQL CARBON EDIT}} Add override for not inlining the sourcemap during build so we can get code coverage - it
|
||||||
// currently expects a *.map.js file to exist next to the source file for proper source mapping
|
// currently expects a *.map.js file to exist next to the source file for proper source mapping
|
||||||
if (!build && !process.env['SQL_NO_INLINE_SOURCEMAP']) {
|
if (!build && !process.env['SQL_NO_INLINE_SOURCEMAP']) {
|
||||||
@@ -52,7 +52,7 @@ function createCompile(src, build, emitError, transpileOnly) {
|
|||||||
console.warn('* and re-run the build/watch task *');
|
console.warn('* and re-run the build/watch task *');
|
||||||
console.warn('********************************************************************************************');
|
console.warn('********************************************************************************************');
|
||||||
}
|
}
|
||||||
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
|
const compilation = tsb.create(projectPath, overrideOptions, { verbose: false, transpileOnly }, err => reporter(err));
|
||||||
function pipeline(token) {
|
function pipeline(token) {
|
||||||
const bom = require('gulp-bom');
|
const bom = require('gulp-bom');
|
||||||
const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path));
|
const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path));
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function createCompile(src: string, build: boolean, emitError: boolean, transpil
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
|
const compilation = tsb.create(projectPath, overrideOptions, { verbose: false, transpileOnly }, err => reporter(err));
|
||||||
|
|
||||||
function pipeline(token?: util.ICancellationToken) {
|
function pipeline(token?: util.ICancellationToken) {
|
||||||
const bom = require('gulp-bom') as typeof import('gulp-bom');
|
const bom = require('gulp-bom') as typeof import('gulp-bom');
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ function asYarnDependency(prefix, tree) {
|
|||||||
return { name, version, path: dependencyPath, children };
|
return { name, version, path: dependencyPath, children };
|
||||||
}
|
}
|
||||||
function getYarnProductionDependencies(cwd) {
|
function getYarnProductionDependencies(cwd) {
|
||||||
const raw = cp.execSync('yarn list --json', { cwd, encoding: 'utf8', env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'production' }), stdio: [null, null, 'inherit'] });
|
const raw = cp.execSync('yarn list --json', { cwd, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' }, stdio: [null, null, 'inherit'] });
|
||||||
const match = /^{"type":"tree".*$/m.exec(raw);
|
const match = /^{"type":"tree".*$/m.exec(raw);
|
||||||
if (!match || match.length !== 1) {
|
if (!match || match.length !== 1) {
|
||||||
throw new Error('Could not parse result of `yarn list --json`');
|
throw new Error('Could not parse result of `yarn list --json`');
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSyn
|
|||||||
function darwinBundleDocumentType(extensions, icon, nameOrSuffix, utis) {
|
function darwinBundleDocumentType(extensions, icon, nameOrSuffix, utis) {
|
||||||
// If given a suffix, generate a name from it. If not given anything, default to 'document'
|
// If given a suffix, generate a name from it. If not given anything, default to 'document'
|
||||||
if (isDocumentSuffix(nameOrSuffix) || !nameOrSuffix) {
|
if (isDocumentSuffix(nameOrSuffix) || !nameOrSuffix) {
|
||||||
nameOrSuffix = icon.charAt(0).toUpperCase() + icon.slice(1) + ' ' + (nameOrSuffix !== null && nameOrSuffix !== void 0 ? nameOrSuffix : 'document');
|
nameOrSuffix = icon.charAt(0).toUpperCase() + icon.slice(1) + ' ' + (nameOrSuffix ?? 'document');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: nameOrSuffix,
|
name: nameOrSuffix,
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ module.exports = {
|
|||||||
return {
|
return {
|
||||||
// /.../
|
// /.../
|
||||||
['Literal[regex]']: (node) => {
|
['Literal[regex]']: (node) => {
|
||||||
var _a;
|
const pattern = node.regex?.pattern;
|
||||||
const pattern = (_a = node.regex) === null || _a === void 0 ? void 0 : _a.pattern;
|
|
||||||
if (_containsLookBehind(pattern)) {
|
if (_containsLookBehind(pattern)) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
|
|||||||
@@ -14,9 +14,8 @@ module.exports = new class ApiLiteralOrTypes {
|
|||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
['TSDeclareFunction Identifier[name=/create.*/]']: (node) => {
|
['TSDeclareFunction Identifier[name=/create.*/]']: (node) => {
|
||||||
var _a;
|
|
||||||
const decl = node.parent;
|
const decl = node.parent;
|
||||||
if (((_a = decl.returnType) === null || _a === void 0 ? void 0 : _a.typeAnnotation.type) !== experimental_utils_1.AST_NODE_TYPES.TSTypeReference) {
|
if (decl.returnType?.typeAnnotation.type !== experimental_utils_1.AST_NODE_TYPES.TSTypeReference) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (decl.returnType.typeAnnotation.typeName.type !== experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
if (decl.returnType.typeAnnotation.typeName.type !== experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ module.exports = new (_a = class ApiEventNaming {
|
|||||||
const verbs = new Set(config.verbs);
|
const verbs = new Set(config.verbs);
|
||||||
return {
|
return {
|
||||||
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => {
|
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => {
|
||||||
var _a, _b;
|
const def = node.parent?.parent?.parent;
|
||||||
const def = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent;
|
|
||||||
const ident = this.getIdent(def);
|
const ident = this.getIdent(def);
|
||||||
if (!ident) {
|
if (!ident) {
|
||||||
// event on unknown structure...
|
// event on unknown structure...
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ module.exports = new (_a = class ApiProviderNaming {
|
|||||||
const allowed = new Set(config.allowed);
|
const allowed = new Set(config.allowed);
|
||||||
return {
|
return {
|
||||||
['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node) => {
|
['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node) => {
|
||||||
var _a;
|
const interfaceName = (node.parent?.parent).id.name;
|
||||||
const interfaceName = ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent).id.name;
|
|
||||||
if (allowed.has(interfaceName)) {
|
if (allowed.has(interfaceName)) {
|
||||||
// allowed
|
// allowed
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -34,14 +34,14 @@ function minifyExtensionResources(input) {
|
|||||||
.pipe(jsonFilter)
|
.pipe(jsonFilter)
|
||||||
.pipe(buffer())
|
.pipe(buffer())
|
||||||
.pipe(es.mapSync((f) => {
|
.pipe(es.mapSync((f) => {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const value = jsoncParser.parse(f.contents.toString('utf8'), errors);
|
const value = jsoncParser.parse(f.contents.toString('utf8'), errors);
|
||||||
if (errors.length === 0) {
|
if (errors.length === 0) {
|
||||||
// file parsed OK => just stringify to drop whitespace and comments
|
// file parsed OK => just stringify to drop whitespace and comments
|
||||||
f.contents = Buffer.from(JSON.stringify(value));
|
f.contents = Buffer.from(JSON.stringify(value));
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}))
|
}))
|
||||||
.pipe(jsonFilter.restore);
|
.pipe(jsonFilter.restore);
|
||||||
}
|
}
|
||||||
function updateExtensionPackageJSON(input, update) {
|
function updateExtensionPackageJSON(input, update) {
|
||||||
@@ -50,10 +50,10 @@ function updateExtensionPackageJSON(input, update) {
|
|||||||
.pipe(packageJsonFilter)
|
.pipe(packageJsonFilter)
|
||||||
.pipe(buffer())
|
.pipe(buffer())
|
||||||
.pipe(es.mapSync((f) => {
|
.pipe(es.mapSync((f) => {
|
||||||
const data = JSON.parse(f.contents.toString('utf8'));
|
const data = JSON.parse(f.contents.toString('utf8'));
|
||||||
f.contents = Buffer.from(JSON.stringify(update(data)));
|
f.contents = Buffer.from(JSON.stringify(update(data)));
|
||||||
return f;
|
return f;
|
||||||
}))
|
}))
|
||||||
.pipe(packageJsonFilter.restore);
|
.pipe(packageJsonFilter.restore);
|
||||||
}
|
}
|
||||||
function fromLocal(extensionPath, forWeb) {
|
function fromLocal(extensionPath, forWeb) {
|
||||||
@@ -95,11 +95,11 @@ function fromLocalWebpack(extensionPath, webpackConfigFileName) {
|
|||||||
const files = fileNames
|
const files = fileNames
|
||||||
.map(fileName => path.join(extensionPath, fileName))
|
.map(fileName => path.join(extensionPath, fileName))
|
||||||
.map(filePath => new File({
|
.map(filePath => new File({
|
||||||
path: filePath,
|
path: filePath,
|
||||||
stat: fs.statSync(filePath),
|
stat: fs.statSync(filePath),
|
||||||
base: extensionPath,
|
base: extensionPath,
|
||||||
contents: fs.createReadStream(filePath)
|
contents: fs.createReadStream(filePath)
|
||||||
}));
|
}));
|
||||||
// check for a webpack configuration files, then invoke webpack
|
// check for a webpack configuration files, then invoke webpack
|
||||||
// and merge its output with the files stream.
|
// and merge its output with the files stream.
|
||||||
const webpackConfigLocations = glob.sync(path.join(extensionPath, '**', webpackConfigFileName), { ignore: ['**/node_modules'] });
|
const webpackConfigLocations = glob.sync(path.join(extensionPath, '**', webpackConfigFileName), { ignore: ['**/node_modules'] });
|
||||||
@@ -119,24 +119,27 @@ function fromLocalWebpack(extensionPath, webpackConfigFileName) {
|
|||||||
};
|
};
|
||||||
const exportedConfig = require(webpackConfigPath);
|
const exportedConfig = require(webpackConfigPath);
|
||||||
return (Array.isArray(exportedConfig) ? exportedConfig : [exportedConfig]).map(config => {
|
return (Array.isArray(exportedConfig) ? exportedConfig : [exportedConfig]).map(config => {
|
||||||
const webpackConfig = Object.assign(Object.assign({}, config), { mode: 'production' });
|
const webpackConfig = {
|
||||||
|
...config,
|
||||||
|
...{ mode: 'production' }
|
||||||
|
};
|
||||||
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
|
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
|
||||||
return webpackGulp(webpackConfig, webpack, webpackDone)
|
return webpackGulp(webpackConfig, webpack, webpackDone)
|
||||||
.pipe(es.through(function (data) {
|
.pipe(es.through(function (data) {
|
||||||
data.stat = data.stat || {};
|
data.stat = data.stat || {};
|
||||||
data.base = extensionPath;
|
data.base = extensionPath;
|
||||||
this.emit('data', data);
|
this.emit('data', data);
|
||||||
}))
|
}))
|
||||||
.pipe(es.through(function (data) {
|
.pipe(es.through(function (data) {
|
||||||
// source map handling:
|
// source map handling:
|
||||||
// * rewrite sourceMappingURL
|
// * rewrite sourceMappingURL
|
||||||
// * save to disk so that upload-task picks this up
|
// * save to disk so that upload-task picks this up
|
||||||
const contents = data.contents.toString('utf8');
|
const contents = data.contents.toString('utf8');
|
||||||
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
|
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
|
||||||
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
||||||
}), 'utf8');
|
}), 'utf8');
|
||||||
this.emit('data', data);
|
this.emit('data', data);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
es.merge(...webpackStreams, es.readArray(files))
|
es.merge(...webpackStreams, es.readArray(files))
|
||||||
@@ -158,16 +161,16 @@ function fromLocalNormal(extensionPath) {
|
|||||||
const result = es.through();
|
const result = es.through();
|
||||||
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn })
|
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn })
|
||||||
.then(fileNames => {
|
.then(fileNames => {
|
||||||
const files = fileNames
|
const files = fileNames
|
||||||
.map(fileName => path.join(extensionPath, fileName))
|
.map(fileName => path.join(extensionPath, fileName))
|
||||||
.map(filePath => new File({
|
.map(filePath => new File({
|
||||||
path: filePath,
|
path: filePath,
|
||||||
stat: fs.statSync(filePath),
|
stat: fs.statSync(filePath),
|
||||||
base: extensionPath,
|
base: extensionPath,
|
||||||
contents: fs.createReadStream(filePath)
|
contents: fs.createReadStream(filePath)
|
||||||
}));
|
}));
|
||||||
es.readArray(files).pipe(result);
|
es.readArray(files).pipe(result);
|
||||||
})
|
})
|
||||||
.catch(err => result.emit('error', err));
|
.catch(err => result.emit('error', err));
|
||||||
return result.pipe((0, stats_1.createStatsStream)(path.basename(extensionPath)));
|
return result.pipe((0, stats_1.createStatsStream)(path.basename(extensionPath)));
|
||||||
}
|
}
|
||||||
@@ -209,7 +212,10 @@ const ghApiHeaders = {
|
|||||||
if (process.env.GITHUB_TOKEN) {
|
if (process.env.GITHUB_TOKEN) {
|
||||||
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
|
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
|
||||||
}
|
}
|
||||||
const ghDownloadHeaders = Object.assign(Object.assign({}, ghApiHeaders), { Accept: 'application/octet-stream' });
|
const ghDownloadHeaders = {
|
||||||
|
...ghApiHeaders,
|
||||||
|
Accept: 'application/octet-stream',
|
||||||
|
};
|
||||||
function fromGithub({ name, version, repo, metadata }) {
|
function fromGithub({ name, version, repo, metadata }) {
|
||||||
const remote = require('gulp-remote-retry-src');
|
const remote = require('gulp-remote-retry-src');
|
||||||
const json = require('gulp-json-editor');
|
const json = require('gulp-json-editor');
|
||||||
@@ -244,6 +250,7 @@ const excludedExtensions = [
|
|||||||
'ms-vscode.node-debug',
|
'ms-vscode.node-debug',
|
||||||
'ms-vscode.node-debug2',
|
'ms-vscode.node-debug2',
|
||||||
'vscode-custom-editor-tests',
|
'vscode-custom-editor-tests',
|
||||||
|
'vscode-notebook-tests',
|
||||||
'integration-tests', // {{SQL CARBON EDIT}}
|
'integration-tests', // {{SQL CARBON EDIT}}
|
||||||
];
|
];
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
@@ -258,7 +265,6 @@ const externalExtensions = [
|
|||||||
'arc',
|
'arc',
|
||||||
'asde-deployment',
|
'asde-deployment',
|
||||||
'azcli',
|
'azcli',
|
||||||
'azurehybridtoolkit',
|
|
||||||
'azuremonitor',
|
'azuremonitor',
|
||||||
'cms',
|
'cms',
|
||||||
'dacpac',
|
'dacpac',
|
||||||
@@ -324,11 +330,11 @@ function isWebExtension(manifest) {
|
|||||||
function packageLocalExtensionsStream(forWeb) {
|
function packageLocalExtensionsStream(forWeb) {
|
||||||
const localExtensionsDescriptions = (glob.sync('extensions/*/package.json')
|
const localExtensionsDescriptions = (glob.sync('extensions/*/package.json')
|
||||||
.map(manifestPath => {
|
.map(manifestPath => {
|
||||||
const absoluteManifestPath = path.join(root, manifestPath);
|
const absoluteManifestPath = path.join(root, manifestPath);
|
||||||
const extensionPath = path.dirname(path.join(root, manifestPath));
|
const extensionPath = path.dirname(path.join(root, manifestPath));
|
||||||
const extensionName = path.basename(extensionPath);
|
const extensionName = path.basename(extensionPath);
|
||||||
return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath };
|
return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath };
|
||||||
})
|
})
|
||||||
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
||||||
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
||||||
.filter(({ name }) => externalExtensions.indexOf(name) === -1) // {{SQL CARBON EDIT}} Remove external Extensions with separate package
|
.filter(({ name }) => externalExtensions.indexOf(name) === -1) // {{SQL CARBON EDIT}} Remove external Extensions with separate package
|
||||||
@@ -359,15 +365,15 @@ function packageMarketplaceExtensionsStream(forWeb, galleryServiceUrl) {
|
|||||||
];
|
];
|
||||||
const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions
|
const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions
|
||||||
.map(extension => {
|
.map(extension => {
|
||||||
const input = (galleryServiceUrl ? fromMarketplace(galleryServiceUrl, extension) : fromGithub(extension))
|
const input = (galleryServiceUrl ? fromMarketplace(galleryServiceUrl, extension) : fromGithub(extension))
|
||||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||||
return updateExtensionPackageJSON(input, (data) => {
|
return updateExtensionPackageJSON(input, (data) => {
|
||||||
delete data.scripts;
|
delete data.scripts;
|
||||||
delete data.dependencies;
|
delete data.dependencies;
|
||||||
delete data.devDependencies;
|
delete data.devDependencies;
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
})));
|
})));
|
||||||
return (marketplaceExtensionsStream
|
return (marketplaceExtensionsStream
|
||||||
.pipe(util2.setExecutableBit(['**/*.sh'])));
|
.pipe(util2.setExecutableBit(['**/*.sh'])));
|
||||||
}
|
}
|
||||||
@@ -412,10 +418,10 @@ exports.scanBuiltinExtensions = scanBuiltinExtensions;
|
|||||||
function packageExternalExtensionsStream() {
|
function packageExternalExtensionsStream() {
|
||||||
const extenalExtensionDescriptions = glob.sync('extensions/*/package.json')
|
const extenalExtensionDescriptions = glob.sync('extensions/*/package.json')
|
||||||
.map(manifestPath => {
|
.map(manifestPath => {
|
||||||
const extensionPath = path.dirname(path.join(root, manifestPath));
|
const extensionPath = path.dirname(path.join(root, manifestPath));
|
||||||
const extensionName = path.basename(extensionPath);
|
const extensionName = path.basename(extensionPath);
|
||||||
return { name: extensionName, path: extensionPath };
|
return { name: extensionName, path: extensionPath };
|
||||||
})
|
})
|
||||||
.filter(({ name }) => externalExtensions.indexOf(name) >= 0 || exports.vscodeExternalExtensions.indexOf(name) >= 0);
|
.filter(({ name }) => externalExtensions.indexOf(name) >= 0 || exports.vscodeExternalExtensions.indexOf(name) >= 0);
|
||||||
const builtExtensions = extenalExtensionDescriptions.map(extension => {
|
const builtExtensions = extenalExtensionDescriptions.map(extension => {
|
||||||
return fromLocal(extension.path, false)
|
return fromLocal(extension.path, false)
|
||||||
@@ -433,10 +439,10 @@ exports.cleanRebuildExtensions = cleanRebuildExtensions;
|
|||||||
function packageRebuildExtensionsStream() {
|
function packageRebuildExtensionsStream() {
|
||||||
const extenalExtensionDescriptions = glob.sync('extensions/*/package.json')
|
const extenalExtensionDescriptions = glob.sync('extensions/*/package.json')
|
||||||
.map(manifestPath => {
|
.map(manifestPath => {
|
||||||
const extensionPath = path.dirname(path.join(root, manifestPath));
|
const extensionPath = path.dirname(path.join(root, manifestPath));
|
||||||
const extensionName = path.basename(extensionPath);
|
const extensionName = path.basename(extensionPath);
|
||||||
return { name: extensionName, path: extensionPath };
|
return { name: extensionName, path: extensionPath };
|
||||||
})
|
})
|
||||||
.filter(({ name }) => rebuildExtensions.indexOf(name) >= 0);
|
.filter(({ name }) => rebuildExtensions.indexOf(name) >= 0);
|
||||||
const builtExtensions = extenalExtensionDescriptions.map(extension => {
|
const builtExtensions = extenalExtensionDescriptions.map(extension => {
|
||||||
return fromLocal(extension.path, false)
|
return fromLocal(extension.path, false)
|
||||||
@@ -530,7 +536,7 @@ async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
|
|||||||
reject();
|
reject();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reporter(stats === null || stats === void 0 ? void 0 : stats.toJson());
|
reporter(stats?.toJson());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -541,7 +547,7 @@ async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
|
|||||||
reject();
|
reject();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reporter(stats === null || stats === void 0 ? void 0 : stats.toJson());
|
reporter(stats?.toJson());
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1012,7 +1012,7 @@ function prepareI18nFiles() {
|
|||||||
}
|
}
|
||||||
exports.prepareI18nFiles = prepareI18nFiles;
|
exports.prepareI18nFiles = prepareI18nFiles;
|
||||||
function createI18nFile(originalFilePath, messages) {
|
function createI18nFile(originalFilePath, messages) {
|
||||||
const result = Object.create(null);
|
let result = Object.create(null);
|
||||||
result[''] = [
|
result[''] = [
|
||||||
'--------------------------------------------------------------------------------------------',
|
'--------------------------------------------------------------------------------------------',
|
||||||
'Copyright (c) Microsoft Corporation. All rights reserved.',
|
'Copyright (c) Microsoft Corporation. All rights reserved.',
|
||||||
@@ -1035,16 +1035,16 @@ function createI18nFile(originalFilePath, messages) {
|
|||||||
exports.createI18nFile = createI18nFile;
|
exports.createI18nFile = createI18nFile;
|
||||||
exports.i18nPackVersion = '1.0.0'; // {{SQL CARBON EDIT}} Needed in locfunc.
|
exports.i18nPackVersion = '1.0.0'; // {{SQL CARBON EDIT}} Needed in locfunc.
|
||||||
function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pseudo = false) {
|
function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pseudo = false) {
|
||||||
let parsePromises = [];
|
const parsePromises = [];
|
||||||
let mainPack = { version: exports.i18nPackVersion, contents: {} };
|
const mainPack = { version: exports.i18nPackVersion, contents: {} };
|
||||||
let extensionsPacks = {};
|
const extensionsPacks = {};
|
||||||
let errors = [];
|
const errors = [];
|
||||||
return (0, event_stream_1.through)(function (xlf) {
|
return (0, event_stream_1.through)(function (xlf) {
|
||||||
let project = path.basename(path.dirname(path.dirname(xlf.relative)));
|
const project = path.basename(path.dirname(path.dirname(xlf.relative)));
|
||||||
let resource = path.basename(xlf.relative, '.xlf');
|
const resource = path.basename(xlf.relative, '.xlf');
|
||||||
let contents = xlf.contents.toString();
|
const contents = xlf.contents.toString();
|
||||||
log(`Found ${project}: ${resource}`);
|
log(`Found ${project}: ${resource}`);
|
||||||
let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents);
|
const parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents);
|
||||||
parsePromises.push(parsePromise);
|
parsePromises.push(parsePromise);
|
||||||
parsePromise.then(resolvedFiles => {
|
parsePromise.then(resolvedFiles => {
|
||||||
resolvedFiles.forEach(file => {
|
resolvedFiles.forEach(file => {
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ const RULES = [
|
|||||||
},
|
},
|
||||||
// Common: vs/platform/native/common/native.ts
|
// Common: vs/platform/native/common/native.ts
|
||||||
{
|
{
|
||||||
target: '**/vs/platform/native/common/native.ts',
|
target: '**/{vs,sql}/platform/native/common/native.ts',
|
||||||
allowedTypes: CORE_TYPES,
|
allowedTypes: CORE_TYPES,
|
||||||
disallowedTypes: [ /* Ignore native types that are defined from here */],
|
disallowedTypes: [ /* Ignore native types that are defined from here */],
|
||||||
disallowedDefinitions: [
|
disallowedDefinitions: [
|
||||||
@@ -209,7 +209,6 @@ let hasErrors = false;
|
|||||||
function checkFile(program, sourceFile, rule) {
|
function checkFile(program, sourceFile, rule) {
|
||||||
checkNode(sourceFile);
|
checkNode(sourceFile);
|
||||||
function checkNode(node) {
|
function checkNode(node) {
|
||||||
var _a, _b;
|
|
||||||
if (node.kind !== ts.SyntaxKind.Identifier) {
|
if (node.kind !== ts.SyntaxKind.Identifier) {
|
||||||
return ts.forEachChild(node, checkNode); // recurse down
|
return ts.forEachChild(node, checkNode); // recurse down
|
||||||
}
|
}
|
||||||
@@ -224,10 +223,10 @@ function checkFile(program, sourceFile, rule) {
|
|||||||
}
|
}
|
||||||
const parentSymbol = _parentSymbol;
|
const parentSymbol = _parentSymbol;
|
||||||
const text = parentSymbol.getName();
|
const text = parentSymbol.getName();
|
||||||
if ((_a = rule.allowedTypes) === null || _a === void 0 ? void 0 : _a.some(allowed => allowed === text)) {
|
if (rule.allowedTypes?.some(allowed => allowed === text)) {
|
||||||
return; // override
|
return; // override
|
||||||
}
|
}
|
||||||
if ((_b = rule.disallowedTypes) === null || _b === void 0 ? void 0 : _b.some(disallowed => disallowed === text)) {
|
if (rule.disallowedTypes?.some(disallowed => disallowed === text)) {
|
||||||
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
||||||
console.log(`[build/lib/layersChecker.ts]: Reference to type '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`);
|
console.log(`[build/lib/layersChecker.ts]: Reference to type '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`);
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
|
|||||||
@@ -77,6 +77,12 @@ const RULES: IRule[] = [
|
|||||||
skip: true // -> skip all test files
|
skip: true // -> skip all test files
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// TODO@bpasero remove me once electron utility process has landed
|
||||||
|
{
|
||||||
|
target: '**/vs/workbench/services/extensions/electron-sandbox/nativeLocalProcessExtensionHost.ts',
|
||||||
|
skip: true
|
||||||
|
},
|
||||||
|
|
||||||
// Common: vs/base/common/platform.ts
|
// Common: vs/base/common/platform.ts
|
||||||
{
|
{
|
||||||
target: '**/{vs,sql}/base/common/platform.ts',
|
target: '**/{vs,sql}/base/common/platform.ts',
|
||||||
@@ -117,7 +123,7 @@ const RULES: IRule[] = [
|
|||||||
|
|
||||||
// Common: vs/platform/native/common/native.ts
|
// Common: vs/platform/native/common/native.ts
|
||||||
{
|
{
|
||||||
target: '**/vs/platform/native/common/native.ts',
|
target: '**/{vs,sql}/platform/native/common/native.ts',
|
||||||
allowedTypes: CORE_TYPES,
|
allowedTypes: CORE_TYPES,
|
||||||
disallowedTypes: [/* Ignore native types that are defined from here */],
|
disallowedTypes: [/* Ignore native types that are defined from here */],
|
||||||
disallowedDefinitions: [
|
disallowedDefinitions: [
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ function updateMainI18nFile(existingTranslationFilePath, originalFilePath, messa
|
|||||||
delete objectContents[`${contentKey}`];
|
delete objectContents[`${contentKey}`];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
messages.contents = Object.assign(Object.assign({}, objectContents), messages.contents);
|
messages.contents = { ...objectContents, ...messages.contents };
|
||||||
result[''] = [
|
result[''] = [
|
||||||
'--------------------------------------------------------------------------------------------',
|
'--------------------------------------------------------------------------------------------',
|
||||||
'Copyright (c) Microsoft Corporation. All rights reserved.',
|
'Copyright (c) Microsoft Corporation. All rights reserved.',
|
||||||
@@ -141,9 +141,7 @@ function modifyI18nPackFiles(existingTranslationFolder, resultingTranslationPath
|
|||||||
this.queue(translatedExtFile);
|
this.queue(translatedExtFile);
|
||||||
// exclude altered vscode extensions from having a new path even if we provide a new I18n file.
|
// exclude altered vscode extensions from having a new path even if we provide a new I18n file.
|
||||||
if (alteredVSCodeExtensions.indexOf(extension) === -1) {
|
if (alteredVSCodeExtensions.indexOf(extension) === -1) {
|
||||||
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
|
let adsExtensionId = 'Microsoft.' + extension;
|
||||||
//(Other extensions need to have publisher appended in front as their ID.)
|
|
||||||
let adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
|
|
||||||
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
|
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +246,7 @@ function refreshLangpacks() {
|
|||||||
try {
|
try {
|
||||||
fs.statSync(locExtFolder);
|
fs.statSync(locExtFolder);
|
||||||
}
|
}
|
||||||
catch (_a) {
|
catch {
|
||||||
console.log('Language is not included in ADS yet: ' + langId);
|
console.log('Language is not included in ADS yet: ' + langId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -311,7 +309,7 @@ function refreshLangpacks() {
|
|||||||
}
|
}
|
||||||
fs.statSync(path.join(translationDataFolder, curr.path.replace('./translations', '')));
|
fs.statSync(path.join(translationDataFolder, curr.path.replace('./translations', '')));
|
||||||
}
|
}
|
||||||
catch (_a) {
|
catch {
|
||||||
nonExistantExtensions.push(curr);
|
nonExistantExtensions.push(curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,7 +363,7 @@ function renameVscodeLangpacks() {
|
|||||||
try {
|
try {
|
||||||
fs.statSync(locVSCODEFolder);
|
fs.statSync(locVSCODEFolder);
|
||||||
}
|
}
|
||||||
catch (_a) {
|
catch {
|
||||||
console.log('vscode pack is not in ADS yet: ' + langId);
|
console.log('vscode pack is not in ADS yet: ' + langId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const child_process_1 = require("child_process");
|
const child_process_1 = require("child_process");
|
||||||
@@ -95,10 +95,6 @@ class BooleanPolicy extends BasePolicy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class IntPolicy extends BasePolicy {
|
class IntPolicy extends BasePolicy {
|
||||||
constructor(name, category, minimumVersion, description, moduleName, defaultValue) {
|
|
||||||
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
static from(name, category, minimumVersion, description, moduleName, settingNode) {
|
static from(name, category, minimumVersion, description, moduleName, settingNode) {
|
||||||
const type = getStringProperty(settingNode, 'type');
|
const type = getStringProperty(settingNode, 'type');
|
||||||
if (type !== 'number') {
|
if (type !== 'number') {
|
||||||
@@ -110,6 +106,10 @@ class IntPolicy extends BasePolicy {
|
|||||||
}
|
}
|
||||||
return new IntPolicy(name, category, minimumVersion, description, moduleName, defaultValue);
|
return new IntPolicy(name, category, minimumVersion, description, moduleName, defaultValue);
|
||||||
}
|
}
|
||||||
|
constructor(name, category, minimumVersion, description, moduleName, defaultValue) {
|
||||||
|
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
renderADMXElements() {
|
renderADMXElements() {
|
||||||
return [
|
return [
|
||||||
`<decimal id="${this.name}" valueName="${this.name}" />`
|
`<decimal id="${this.name}" valueName="${this.name}" />`
|
||||||
@@ -139,11 +139,6 @@ class StringPolicy extends BasePolicy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class StringEnumPolicy extends BasePolicy {
|
class StringEnumPolicy extends BasePolicy {
|
||||||
constructor(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions) {
|
|
||||||
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
|
|
||||||
this.enum_ = enum_;
|
|
||||||
this.enumDescriptions = enumDescriptions;
|
|
||||||
}
|
|
||||||
static from(name, category, minimumVersion, description, moduleName, settingNode) {
|
static from(name, category, minimumVersion, description, moduleName, settingNode) {
|
||||||
const type = getStringProperty(settingNode, 'type');
|
const type = getStringProperty(settingNode, 'type');
|
||||||
if (type !== 'string') {
|
if (type !== 'string') {
|
||||||
@@ -165,6 +160,11 @@ class StringEnumPolicy extends BasePolicy {
|
|||||||
}
|
}
|
||||||
return new StringEnumPolicy(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions);
|
return new StringEnumPolicy(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions);
|
||||||
}
|
}
|
||||||
|
constructor(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions) {
|
||||||
|
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
|
||||||
|
this.enum_ = enum_;
|
||||||
|
this.enumDescriptions = enumDescriptions;
|
||||||
|
}
|
||||||
renderADMXElements() {
|
renderADMXElements() {
|
||||||
return [
|
return [
|
||||||
`<enum id="${this.name}" valueName="${this.name}">`,
|
`<enum id="${this.name}" valueName="${this.name}">`,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const rootDir = path.resolve(__dirname, '..', '..');
|
|||||||
function runProcess(command, args = []) {
|
function runProcess(command, args = []) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const child = (0, child_process_1.spawn)(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env });
|
const child = (0, child_process_1.spawn)(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env });
|
||||||
child.on('exit', err => !err ? resolve() : process.exit(err !== null && err !== void 0 ? err : 1));
|
child.on('exit', err => !err ? resolve() : process.exit(err ?? 1));
|
||||||
child.on('error', reject);
|
child.on('error', reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ async function exists(subdir) {
|
|||||||
await fs_1.promises.stat(path.join(rootDir, subdir));
|
await fs_1.promises.stat(path.join(rootDir, subdir));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (_a) {
|
catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ function writeFile(filePath, contents) {
|
|||||||
fs.writeFileSync(filePath, contents);
|
fs.writeFileSync(filePath, contents);
|
||||||
}
|
}
|
||||||
function extractEditor(options) {
|
function extractEditor(options) {
|
||||||
var _a;
|
|
||||||
const ts = require('typescript');
|
const ts = require('typescript');
|
||||||
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString());
|
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString());
|
||||||
let compilerOptions;
|
let compilerOptions;
|
||||||
@@ -49,7 +48,7 @@ function extractEditor(options) {
|
|||||||
// Take the extra included .d.ts files from `tsconfig.monaco.json`
|
// Take the extra included .d.ts files from `tsconfig.monaco.json`
|
||||||
options.typings = tsConfig.include.filter(includedFile => /\.d\.ts$/.test(includedFile));
|
options.typings = tsConfig.include.filter(includedFile => /\.d\.ts$/.test(includedFile));
|
||||||
// Add extra .d.ts files from `node_modules/@types/`
|
// Add extra .d.ts files from `node_modules/@types/`
|
||||||
if (Array.isArray((_a = options.compilerOptions) === null || _a === void 0 ? void 0 : _a.types)) {
|
if (Array.isArray(options.compilerOptions?.types)) {
|
||||||
options.compilerOptions.types.forEach((type) => {
|
options.compilerOptions.types.forEach((type) => {
|
||||||
options.typings.push(`../node_modules/@types/${type}/index.d.ts`);
|
options.typings.push(`../node_modules/@types/${type}/index.d.ts`);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ var ShakeLevel;
|
|||||||
})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {}));
|
})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {}));
|
||||||
function toStringShakeLevel(shakeLevel) {
|
function toStringShakeLevel(shakeLevel) {
|
||||||
switch (shakeLevel) {
|
switch (shakeLevel) {
|
||||||
case 0 /* Files */:
|
case 0 /* ShakeLevel.Files */:
|
||||||
return 'Files (0)';
|
return 'Files (0)';
|
||||||
case 1 /* InnerFile */:
|
case 1 /* ShakeLevel.InnerFile */:
|
||||||
return 'InnerFile (1)';
|
return 'InnerFile (1)';
|
||||||
case 2 /* ClassMembers */:
|
case 2 /* ShakeLevel.ClassMembers */:
|
||||||
return 'ClassMembers (2)';
|
return 'ClassMembers (2)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ var NodeColor;
|
|||||||
NodeColor[NodeColor["Black"] = 2] = "Black";
|
NodeColor[NodeColor["Black"] = 2] = "Black";
|
||||||
})(NodeColor || (NodeColor = {}));
|
})(NodeColor || (NodeColor = {}));
|
||||||
function getColor(node) {
|
function getColor(node) {
|
||||||
return node.$$$color || 0 /* White */;
|
return node.$$$color || 0 /* NodeColor.White */;
|
||||||
}
|
}
|
||||||
function setColor(node, color) {
|
function setColor(node, color) {
|
||||||
node.$$$color = color;
|
node.$$$color = color;
|
||||||
@@ -237,7 +237,7 @@ function isNeededSourceFile(node) {
|
|||||||
function nodeOrParentIsBlack(node) {
|
function nodeOrParentIsBlack(node) {
|
||||||
while (node) {
|
while (node) {
|
||||||
const color = getColor(node);
|
const color = getColor(node);
|
||||||
if (color === 2 /* Black */) {
|
if (color === 2 /* NodeColor.Black */) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
node = node.parent;
|
node = node.parent;
|
||||||
@@ -245,7 +245,7 @@ function nodeOrParentIsBlack(node) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function nodeOrChildIsBlack(node) {
|
function nodeOrChildIsBlack(node) {
|
||||||
if (getColor(node) === 2 /* Black */) {
|
if (getColor(node) === 2 /* NodeColor.Black */) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (const child of node.getChildren()) {
|
for (const child of node.getChildren()) {
|
||||||
@@ -309,10 +309,10 @@ function markNodes(ts, languageService, options) {
|
|||||||
if (!program) {
|
if (!program) {
|
||||||
throw new Error('Could not get program from language service');
|
throw new Error('Could not get program from language service');
|
||||||
}
|
}
|
||||||
if (options.shakeLevel === 0 /* Files */) {
|
if (options.shakeLevel === 0 /* ShakeLevel.Files */) {
|
||||||
// Mark all source files Black
|
// Mark all source files Black
|
||||||
program.getSourceFiles().forEach((sourceFile) => {
|
program.getSourceFiles().forEach((sourceFile) => {
|
||||||
setColor(sourceFile, 2 /* Black */);
|
setColor(sourceFile, 2 /* NodeColor.Black */);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -324,7 +324,7 @@ function markNodes(ts, languageService, options) {
|
|||||||
sourceFile.forEachChild((node) => {
|
sourceFile.forEachChild((node) => {
|
||||||
if (ts.isImportDeclaration(node)) {
|
if (ts.isImportDeclaration(node)) {
|
||||||
if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) {
|
if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||||
setColor(node, 2 /* Black */);
|
setColor(node, 2 /* NodeColor.Black */);
|
||||||
enqueueImport(node, node.moduleSpecifier.text);
|
enqueueImport(node, node.moduleSpecifier.text);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -332,7 +332,7 @@ function markNodes(ts, languageService, options) {
|
|||||||
if (ts.isExportDeclaration(node)) {
|
if (ts.isExportDeclaration(node)) {
|
||||||
if (!node.exportClause && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
if (!node.exportClause && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||||
// export * from "foo";
|
// export * from "foo";
|
||||||
setColor(node, 2 /* Black */);
|
setColor(node, 2 /* NodeColor.Black */);
|
||||||
enqueueImport(node, node.moduleSpecifier.text);
|
enqueueImport(node, node.moduleSpecifier.text);
|
||||||
}
|
}
|
||||||
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
|
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
|
||||||
@@ -373,21 +373,21 @@ function markNodes(ts, languageService, options) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
function enqueue_gray(node) {
|
function enqueue_gray(node) {
|
||||||
if (nodeOrParentIsBlack(node) || getColor(node) === 1 /* Gray */) {
|
if (nodeOrParentIsBlack(node) || getColor(node) === 1 /* NodeColor.Gray */) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setColor(node, 1 /* Gray */);
|
setColor(node, 1 /* NodeColor.Gray */);
|
||||||
gray_queue.push(node);
|
gray_queue.push(node);
|
||||||
}
|
}
|
||||||
function enqueue_black(node) {
|
function enqueue_black(node) {
|
||||||
const previousColor = getColor(node);
|
const previousColor = getColor(node);
|
||||||
if (previousColor === 2 /* Black */) {
|
if (previousColor === 2 /* NodeColor.Black */) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (previousColor === 1 /* Gray */) {
|
if (previousColor === 1 /* NodeColor.Gray */) {
|
||||||
// remove from gray queue
|
// remove from gray queue
|
||||||
gray_queue.splice(gray_queue.indexOf(node), 1);
|
gray_queue.splice(gray_queue.indexOf(node), 1);
|
||||||
setColor(node, 0 /* White */);
|
setColor(node, 0 /* NodeColor.White */);
|
||||||
// add to black queue
|
// add to black queue
|
||||||
enqueue_black(node);
|
enqueue_black(node);
|
||||||
// move from one queue to the other
|
// move from one queue to the other
|
||||||
@@ -400,7 +400,7 @@ function markNodes(ts, languageService, options) {
|
|||||||
}
|
}
|
||||||
const fileName = node.getSourceFile().fileName;
|
const fileName = node.getSourceFile().fileName;
|
||||||
if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) {
|
if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) {
|
||||||
setColor(node, 2 /* Black */);
|
setColor(node, 2 /* NodeColor.Black */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const sourceFile = node.getSourceFile();
|
const sourceFile = node.getSourceFile();
|
||||||
@@ -411,9 +411,9 @@ function markNodes(ts, languageService, options) {
|
|||||||
if (ts.isSourceFile(node)) {
|
if (ts.isSourceFile(node)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setColor(node, 2 /* Black */);
|
setColor(node, 2 /* NodeColor.Black */);
|
||||||
black_queue.push(node);
|
black_queue.push(node);
|
||||||
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) {
|
if (options.shakeLevel === 2 /* ShakeLevel.ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) {
|
||||||
const references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth());
|
const references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth());
|
||||||
if (references) {
|
if (references) {
|
||||||
for (let i = 0, len = references.length; i < len; i++) {
|
for (let i = 0, len = references.length; i < len; i++) {
|
||||||
@@ -476,7 +476,7 @@ function markNodes(ts, languageService, options) {
|
|||||||
if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) {
|
if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) {
|
||||||
gray_queue.splice(i, 1);
|
gray_queue.splice(i, 1);
|
||||||
black_queue.push(node);
|
black_queue.push(node);
|
||||||
setColor(node, 2 /* Black */);
|
setColor(node, 2 /* NodeColor.Black */);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,7 +506,7 @@ function markNodes(ts, languageService, options) {
|
|||||||
// (they can be the declaration of a module import)
|
// (they can be the declaration of a module import)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(ts, program, checker, declaration)) {
|
if (options.shakeLevel === 2 /* ShakeLevel.ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(ts, program, checker, declaration)) {
|
||||||
enqueue_black(declaration.name);
|
enqueue_black(declaration.name);
|
||||||
for (let j = 0; j < declaration.members.length; j++) {
|
for (let j = 0; j < declaration.members.length; j++) {
|
||||||
const member = declaration.members[j];
|
const member = declaration.members[j];
|
||||||
@@ -556,7 +556,7 @@ function markNodes(ts, languageService, options) {
|
|||||||
const aliased = checker.getAliasedSymbol(symbol);
|
const aliased = checker.getAliasedSymbol(symbol);
|
||||||
if (aliased.declarations && aliased.declarations.length > 0) {
|
if (aliased.declarations && aliased.declarations.length > 0) {
|
||||||
if (nodeOrParentIsBlack(aliased.declarations[0]) || nodeOrChildIsBlack(aliased.declarations[0])) {
|
if (nodeOrParentIsBlack(aliased.declarations[0]) || nodeOrChildIsBlack(aliased.declarations[0])) {
|
||||||
setColor(node, 2 /* Black */);
|
setColor(node, 2 /* NodeColor.Black */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -603,7 +603,7 @@ function generateResult(ts, languageService, shakeLevel) {
|
|||||||
result += data;
|
result += data;
|
||||||
}
|
}
|
||||||
function writeMarkedNodes(node) {
|
function writeMarkedNodes(node) {
|
||||||
if (getColor(node) === 2 /* Black */) {
|
if (getColor(node) === 2 /* NodeColor.Black */) {
|
||||||
return keep(node);
|
return keep(node);
|
||||||
}
|
}
|
||||||
// Always keep certain top-level statements
|
// Always keep certain top-level statements
|
||||||
@@ -619,34 +619,34 @@ function generateResult(ts, languageService, shakeLevel) {
|
|||||||
if (ts.isImportDeclaration(node)) {
|
if (ts.isImportDeclaration(node)) {
|
||||||
if (node.importClause && node.importClause.namedBindings) {
|
if (node.importClause && node.importClause.namedBindings) {
|
||||||
if (ts.isNamespaceImport(node.importClause.namedBindings)) {
|
if (ts.isNamespaceImport(node.importClause.namedBindings)) {
|
||||||
if (getColor(node.importClause.namedBindings) === 2 /* Black */) {
|
if (getColor(node.importClause.namedBindings) === 2 /* NodeColor.Black */) {
|
||||||
return keep(node);
|
return keep(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const survivingImports = [];
|
const survivingImports = [];
|
||||||
for (const importNode of node.importClause.namedBindings.elements) {
|
for (const importNode of node.importClause.namedBindings.elements) {
|
||||||
if (getColor(importNode) === 2 /* Black */) {
|
if (getColor(importNode) === 2 /* NodeColor.Black */) {
|
||||||
survivingImports.push(importNode.getFullText(sourceFile));
|
survivingImports.push(importNode.getFullText(sourceFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const leadingTriviaWidth = node.getLeadingTriviaWidth();
|
const leadingTriviaWidth = node.getLeadingTriviaWidth();
|
||||||
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
|
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
|
||||||
if (survivingImports.length > 0) {
|
if (survivingImports.length > 0) {
|
||||||
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
|
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* NodeColor.Black */) {
|
||||||
return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||||
}
|
}
|
||||||
return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
|
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* NodeColor.Black */) {
|
||||||
return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (node.importClause && getColor(node.importClause) === 2 /* Black */) {
|
if (node.importClause && getColor(node.importClause) === 2 /* NodeColor.Black */) {
|
||||||
return keep(node);
|
return keep(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,7 +655,7 @@ function generateResult(ts, languageService, shakeLevel) {
|
|||||||
if (node.exportClause && node.moduleSpecifier && ts.isNamedExports(node.exportClause)) {
|
if (node.exportClause && node.moduleSpecifier && ts.isNamedExports(node.exportClause)) {
|
||||||
const survivingExports = [];
|
const survivingExports = [];
|
||||||
for (const exportSpecifier of node.exportClause.elements) {
|
for (const exportSpecifier of node.exportClause.elements) {
|
||||||
if (getColor(exportSpecifier) === 2 /* Black */) {
|
if (getColor(exportSpecifier) === 2 /* NodeColor.Black */) {
|
||||||
survivingExports.push(exportSpecifier.getFullText(sourceFile));
|
survivingExports.push(exportSpecifier.getFullText(sourceFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -666,11 +666,11 @@ function generateResult(ts, languageService, shakeLevel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) {
|
if (shakeLevel === 2 /* ShakeLevel.ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) {
|
||||||
let toWrite = node.getFullText();
|
let toWrite = node.getFullText();
|
||||||
for (let i = node.members.length - 1; i >= 0; i--) {
|
for (let i = node.members.length - 1; i >= 0; i--) {
|
||||||
const member = node.members[i];
|
const member = node.members[i];
|
||||||
if (getColor(member) === 2 /* Black */ || !member.name) {
|
if (getColor(member) === 2 /* NodeColor.Black */ || !member.name) {
|
||||||
// keep method
|
// keep method
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -686,7 +686,7 @@ function generateResult(ts, languageService, shakeLevel) {
|
|||||||
}
|
}
|
||||||
node.forEachChild(writeMarkedNodes);
|
node.forEachChild(writeMarkedNodes);
|
||||||
}
|
}
|
||||||
if (getColor(sourceFile) !== 2 /* Black */) {
|
if (getColor(sourceFile) !== 2 /* NodeColor.Black */) {
|
||||||
if (!nodeOrChildIsBlack(sourceFile)) {
|
if (!nodeOrChildIsBlack(sourceFile)) {
|
||||||
// none of the elements are reachable
|
// none of the elements are reachable
|
||||||
if (isNeededSourceFile(sourceFile)) {
|
if (isNeededSourceFile(sourceFile)) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.createTypeScriptBuilder = exports.CancellationToken = void 0;
|
exports.createTypeScriptBuilder = exports.CancellationToken = void 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.create = void 0;
|
exports.create = void 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.Transpiler = void 0;
|
exports.Transpiler = void 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.graph = exports.strings = exports.collections = void 0;
|
exports.graph = exports.strings = exports.collections = void 0;
|
||||||
|
|||||||
@@ -304,7 +304,6 @@ function getElectronVersion() {
|
|||||||
}
|
}
|
||||||
exports.getElectronVersion = getElectronVersion;
|
exports.getElectronVersion = getElectronVersion;
|
||||||
function acquireWebNodePaths() {
|
function acquireWebNodePaths() {
|
||||||
var _a;
|
|
||||||
const root = path.join(__dirname, '..', '..');
|
const root = path.join(__dirname, '..', '..');
|
||||||
const webPackageJSON = path.join(root, '/remote/web', 'package.json');
|
const webPackageJSON = path.join(root, '/remote/web', 'package.json');
|
||||||
const webPackages = JSON.parse(fs.readFileSync(webPackageJSON, 'utf8')).dependencies;
|
const webPackages = JSON.parse(fs.readFileSync(webPackageJSON, 'utf8')).dependencies;
|
||||||
@@ -312,7 +311,7 @@ function acquireWebNodePaths() {
|
|||||||
for (const key of Object.keys(webPackages)) {
|
for (const key of Object.keys(webPackages)) {
|
||||||
const packageJSON = path.join(root, 'node_modules', key, 'package.json');
|
const packageJSON = path.join(root, 'node_modules', key, 'package.json');
|
||||||
const packageData = JSON.parse(fs.readFileSync(packageJSON, 'utf8'));
|
const packageData = JSON.parse(fs.readFileSync(packageJSON, 'utf8'));
|
||||||
let entryPoint = typeof packageData.browser === 'string' ? packageData.browser : (_a = packageData.main) !== null && _a !== void 0 ? _a : packageData.main; // {{SQL CARBON EDIT}} Some packages (like Turndown) have objects in this field instead of the entry point, fall back to main in that case
|
let entryPoint = typeof packageData.browser === 'string' ? packageData.browser : packageData.main ?? packageData.main; // {{SQL CARBON EDIT}} Some packages (like Turndown) have objects in this field instead of the entry point, fall back to main in that case
|
||||||
// On rare cases a package doesn't have an entrypoint so we assume it has a dist folder with a min.js
|
// On rare cases a package doesn't have an entrypoint so we assume it has a dist folder with a min.js
|
||||||
if (!entryPoint) {
|
if (!entryPoint) {
|
||||||
// TODO @lramos15 remove this when jschardet adds an entrypoint so we can warn on all packages w/out entrypoint
|
// TODO @lramos15 remove this when jschardet adds an entrypoint so we can warn on all packages w/out entrypoint
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.referenceGeneratedDepsByArch = exports.bundledDeps = exports.recommendedDeps = exports.additionalDeps = void 0;
|
exports.referenceGeneratedDepsByArch = exports.bundledDeps = exports.recommendedDeps = exports.additionalDeps = void 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
@@ -9,7 +9,7 @@ const child_process_1 = require("child_process");
|
|||||||
const fs_1 = require("fs");
|
const fs_1 = require("fs");
|
||||||
const os_1 = require("os");
|
const os_1 = require("os");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const dep_lists_1 = require("./dep-lists");
|
const dep_lists_1 = require("./dep-lists"); // {{SQL CARBON EDIT}} Not needed
|
||||||
// A flag that can easily be toggled.
|
// A flag that can easily be toggled.
|
||||||
// Make sure to compile the build directory after toggling the value.
|
// Make sure to compile the build directory after toggling the value.
|
||||||
// If false, we warn about new dependencies if they show up
|
// If false, we warn about new dependencies if they show up
|
||||||
@@ -17,7 +17,7 @@ const dep_lists_1 = require("./dep-lists");
|
|||||||
// If true, we fail the build if there are new dependencies found during that task.
|
// If true, we fail the build if there are new dependencies found during that task.
|
||||||
// The reference dependencies, which one has to update when the new dependencies
|
// The reference dependencies, which one has to update when the new dependencies
|
||||||
// are valid, are in dep-lists.ts
|
// are valid, are in dep-lists.ts
|
||||||
const FAIL_BUILD_FOR_NEW_DEPENDENCIES = true;
|
// const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true; {{ SQL CARBON EDIT}} Not needed
|
||||||
function getDependencies(buildDir, applicationName, arch, sysroot) {
|
function getDependencies(buildDir, applicationName, arch, sysroot) {
|
||||||
// Get the files for which we want to find dependencies.
|
// Get the files for which we want to find dependencies.
|
||||||
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
|
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
|
||||||
@@ -49,18 +49,19 @@ function getDependencies(buildDir, applicationName, arch, sysroot) {
|
|||||||
sortedDependencies = sortedDependencies.filter(dependency => {
|
sortedDependencies = sortedDependencies.filter(dependency => {
|
||||||
return !dep_lists_1.bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
return !dep_lists_1.bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
||||||
});
|
});
|
||||||
const referenceGeneratedDeps = dep_lists_1.referenceGeneratedDepsByArch[arch];
|
/* {{SQL CARBON EDIT}} Not needed
|
||||||
|
const referenceGeneratedDeps = referenceGeneratedDepsByArch[arch];
|
||||||
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
||||||
const failMessage = 'The dependencies list has changed.'
|
const failMessage = 'The dependencies list has changed.'
|
||||||
+ '\nOld:\n' + referenceGeneratedDeps.join('\n')
|
+ '\nOld:\n' + referenceGeneratedDeps.join('\n')
|
||||||
+ '\nNew:\n' + sortedDependencies.join('\n');
|
+ '\nNew:\n' + sortedDependencies.join('\n');
|
||||||
if (FAIL_BUILD_FOR_NEW_DEPENDENCIES) {
|
if (FAIL_BUILD_FOR_NEW_DEPENDENCIES) {
|
||||||
throw new Error(failMessage);
|
throw new Error(failMessage);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
console.warn(failMessage);
|
console.warn(failMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return sortedDependencies;
|
return sortedDependencies;
|
||||||
}
|
}
|
||||||
exports.getDependencies = getDependencies;
|
exports.getDependencies = getDependencies;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { spawnSync } from 'child_process';
|
|||||||
import { constants, statSync } from 'fs';
|
import { constants, statSync } from 'fs';
|
||||||
import { tmpdir } from 'os';
|
import { tmpdir } from 'os';
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import { additionalDeps, bundledDeps, referenceGeneratedDepsByArch } from './dep-lists';
|
import { additionalDeps, bundledDeps/*, referenceGeneratedDepsByArch*/ } from './dep-lists'; // {{SQL CARBON EDIT}} Not needed
|
||||||
import { ArchString } from './types';
|
import { ArchString } from './types';
|
||||||
|
|
||||||
// A flag that can easily be toggled.
|
// A flag that can easily be toggled.
|
||||||
@@ -19,7 +19,7 @@ import { ArchString } from './types';
|
|||||||
// If true, we fail the build if there are new dependencies found during that task.
|
// If true, we fail the build if there are new dependencies found during that task.
|
||||||
// The reference dependencies, which one has to update when the new dependencies
|
// The reference dependencies, which one has to update when the new dependencies
|
||||||
// are valid, are in dep-lists.ts
|
// are valid, are in dep-lists.ts
|
||||||
const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true;
|
// const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true; {{ SQL CARBON EDIT}} Not needed
|
||||||
|
|
||||||
export function getDependencies(buildDir: string, applicationName: string, arch: ArchString, sysroot: string): string[] {
|
export function getDependencies(buildDir: string, applicationName: string, arch: ArchString, sysroot: string): string[] {
|
||||||
// Get the files for which we want to find dependencies.
|
// Get the files for which we want to find dependencies.
|
||||||
@@ -59,6 +59,7 @@ export function getDependencies(buildDir: string, applicationName: string, arch:
|
|||||||
return !bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
return !bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* {{SQL CARBON EDIT}} Not needed
|
||||||
const referenceGeneratedDeps = referenceGeneratedDepsByArch[arch];
|
const referenceGeneratedDeps = referenceGeneratedDepsByArch[arch];
|
||||||
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
||||||
const failMessage = 'The dependencies list has changed.'
|
const failMessage = 'The dependencies list has changed.'
|
||||||
@@ -70,6 +71,7 @@ export function getDependencies(buildDir: string, applicationName: string, arch:
|
|||||||
console.warn(failMessage);
|
console.warn(failMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return sortedDependencies;
|
return sortedDependencies;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getSysroot = void 0;
|
exports.getSysroot = void 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.sysrootInfo = void 0;
|
exports.sysrootInfo = void 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ exports.getDependencies = void 0;
|
|||||||
const child_process_1 = require("child_process");
|
const child_process_1 = require("child_process");
|
||||||
const fs_1 = require("fs");
|
const fs_1 = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const dep_lists_1 = require("./dep-lists");
|
const dep_lists_1 = require("./dep-lists"); // {{SQL CARBON EDIT}} Not needed
|
||||||
// A flag that can easily be toggled.
|
// A flag that can easily be toggled.
|
||||||
// Make sure to compile the build directory after toggling the value.
|
// Make sure to compile the build directory after toggling the value.
|
||||||
// If false, we warn about new dependencies if they show up
|
// If false, we warn about new dependencies if they show up
|
||||||
@@ -16,13 +16,13 @@ const dep_lists_1 = require("./dep-lists");
|
|||||||
// If true, we fail the build if there are new dependencies found during that task.
|
// If true, we fail the build if there are new dependencies found during that task.
|
||||||
// The reference dependencies, which one has to update when the new dependencies
|
// The reference dependencies, which one has to update when the new dependencies
|
||||||
// are valid, are in dep-lists.ts
|
// are valid, are in dep-lists.ts
|
||||||
const FAIL_BUILD_FOR_NEW_DEPENDENCIES = false;
|
// const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = false; // {{SQL CARBON EDIT}} Not needed
|
||||||
function getDependencies(buildDir, applicationName, arch) {
|
function getDependencies(buildDir, applicationName, arch) {
|
||||||
// Get the files for which we want to find dependencies.
|
// Get the files for which we want to find dependencies.
|
||||||
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
|
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
|
||||||
const findResult = (0, child_process_1.spawnSync)('find', [nativeModulesPath, '-name', '*.node']);
|
const findResult = (0, child_process_1.spawnSync)('find', [nativeModulesPath, '-name', '*.node']);
|
||||||
if (findResult.status) {
|
if (findResult.status) {
|
||||||
console.error('Error finding files:');
|
console.error(`Error finding files for ${arch}:`);
|
||||||
console.error(findResult.stderr.toString());
|
console.error(findResult.stderr.toString());
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -48,18 +48,19 @@ function getDependencies(buildDir, applicationName, arch) {
|
|||||||
sortedDependencies = sortedDependencies.filter(dependency => {
|
sortedDependencies = sortedDependencies.filter(dependency => {
|
||||||
return !dep_lists_1.bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
return !dep_lists_1.bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
||||||
});
|
});
|
||||||
const referenceGeneratedDeps = dep_lists_1.referenceGeneratedDepsByArch[arch];
|
/* {{SQL CARBON EDIT}} Not needed
|
||||||
|
const referenceGeneratedDeps = referenceGeneratedDepsByArch[arch];
|
||||||
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
||||||
const failMessage = 'The dependencies list has changed. '
|
const failMessage = 'The dependencies list has changed. '
|
||||||
+ 'Printing newer dependencies list that one can use to compare against referenceGeneratedDeps:\n'
|
+ 'Printing newer dependencies list that one can use to compare against referenceGeneratedDeps:\n'
|
||||||
+ sortedDependencies.join('\n');
|
+ sortedDependencies.join('\n');
|
||||||
if (FAIL_BUILD_FOR_NEW_DEPENDENCIES) {
|
if (FAIL_BUILD_FOR_NEW_DEPENDENCIES) {
|
||||||
throw new Error(failMessage);
|
throw new Error(failMessage);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
console.warn(failMessage);
|
console.warn(failMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return sortedDependencies;
|
return sortedDependencies;
|
||||||
}
|
}
|
||||||
exports.getDependencies = getDependencies;
|
exports.getDependencies = getDependencies;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { spawnSync } from 'child_process';
|
import { spawnSync } from 'child_process';
|
||||||
import { constants, statSync } from 'fs';
|
import { constants, statSync } from 'fs';
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import { additionalDeps, bundledDeps, referenceGeneratedDepsByArch } from './dep-lists';
|
import { additionalDeps, bundledDeps/*, referenceGeneratedDepsByArch*/ } from './dep-lists'; // {{SQL CARBON EDIT}} Not needed
|
||||||
import { ArchString } from './types';
|
import { ArchString } from './types';
|
||||||
|
|
||||||
// A flag that can easily be toggled.
|
// A flag that can easily be toggled.
|
||||||
@@ -16,14 +16,14 @@ import { ArchString } from './types';
|
|||||||
// If true, we fail the build if there are new dependencies found during that task.
|
// If true, we fail the build if there are new dependencies found during that task.
|
||||||
// The reference dependencies, which one has to update when the new dependencies
|
// The reference dependencies, which one has to update when the new dependencies
|
||||||
// are valid, are in dep-lists.ts
|
// are valid, are in dep-lists.ts
|
||||||
const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = false;
|
// const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = false; // {{SQL CARBON EDIT}} Not needed
|
||||||
|
|
||||||
export function getDependencies(buildDir: string, applicationName: string, arch: ArchString): string[] {
|
export function getDependencies(buildDir: string, applicationName: string, arch: ArchString): string[] {
|
||||||
// Get the files for which we want to find dependencies.
|
// Get the files for which we want to find dependencies.
|
||||||
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
|
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
|
||||||
const findResult = spawnSync('find', [nativeModulesPath, '-name', '*.node']);
|
const findResult = spawnSync('find', [nativeModulesPath, '-name', '*.node']);
|
||||||
if (findResult.status) {
|
if (findResult.status) {
|
||||||
console.error('Error finding files:');
|
console.error(`Error finding files for ${arch}:`);
|
||||||
console.error(findResult.stderr.toString());
|
console.error(findResult.stderr.toString());
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,7 @@ export function getDependencies(buildDir: string, applicationName: string, arch:
|
|||||||
return !bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
return !bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* {{SQL CARBON EDIT}} Not needed
|
||||||
const referenceGeneratedDeps = referenceGeneratedDepsByArch[arch];
|
const referenceGeneratedDeps = referenceGeneratedDepsByArch[arch];
|
||||||
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
|
||||||
const failMessage = 'The dependencies list has changed. '
|
const failMessage = 'The dependencies list has changed. '
|
||||||
@@ -68,6 +69,7 @@ export function getDependencies(buildDir: string, applicationName: string, arch:
|
|||||||
console.warn(failMessage);
|
console.warn(failMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return sortedDependencies;
|
return sortedDependencies;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,634 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.execute = exports.run3 = exports.DeclarationResolver = exports.FSProvider = exports.RECIPE_PATH = void 0;
|
|
||||||
const fs = require("fs");
|
|
||||||
const ts = require("typescript");
|
|
||||||
const path = require("path");
|
|
||||||
const fancyLog = require("fancy-log");
|
|
||||||
const ansiColors = require("ansi-colors");
|
|
||||||
const dtsv = '3';
|
|
||||||
const tsfmt = require('../../tsfmt.json');
|
|
||||||
const SRC = path.join(__dirname, '../../src');
|
|
||||||
exports.RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe');
|
|
||||||
const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts');
|
|
||||||
function logErr(message, ...rest) {
|
|
||||||
fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest);
|
|
||||||
}
|
|
||||||
function isDeclaration(a) {
|
|
||||||
return (a.kind === ts.SyntaxKind.InterfaceDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.EnumDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.ClassDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.TypeAliasDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.FunctionDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.ModuleDeclaration);
|
|
||||||
}
|
|
||||||
function visitTopLevelDeclarations(sourceFile, visitor) {
|
|
||||||
let stop = false;
|
|
||||||
let visit = (node) => {
|
|
||||||
if (stop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (node.kind) {
|
|
||||||
case ts.SyntaxKind.InterfaceDeclaration:
|
|
||||||
case ts.SyntaxKind.EnumDeclaration:
|
|
||||||
case ts.SyntaxKind.ClassDeclaration:
|
|
||||||
case ts.SyntaxKind.VariableStatement:
|
|
||||||
case ts.SyntaxKind.TypeAliasDeclaration:
|
|
||||||
case ts.SyntaxKind.FunctionDeclaration:
|
|
||||||
case ts.SyntaxKind.ModuleDeclaration:
|
|
||||||
stop = visitor(node);
|
|
||||||
}
|
|
||||||
if (stop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ts.forEachChild(node, visit);
|
|
||||||
};
|
|
||||||
visit(sourceFile);
|
|
||||||
}
|
|
||||||
function getAllTopLevelDeclarations(sourceFile) {
|
|
||||||
let all = [];
|
|
||||||
visitTopLevelDeclarations(sourceFile, (node) => {
|
|
||||||
if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) {
|
|
||||||
let interfaceDeclaration = node;
|
|
||||||
let triviaStart = interfaceDeclaration.pos;
|
|
||||||
let triviaEnd = interfaceDeclaration.name.pos;
|
|
||||||
let triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd });
|
|
||||||
if (triviaText.indexOf('@internal') === -1) {
|
|
||||||
all.push(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let nodeText = getNodeText(sourceFile, node);
|
|
||||||
if (nodeText.indexOf('@internal') === -1) {
|
|
||||||
all.push(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false /*continue*/;
|
|
||||||
});
|
|
||||||
return all;
|
|
||||||
}
|
|
||||||
function getTopLevelDeclaration(sourceFile, typeName) {
|
|
||||||
let result = null;
|
|
||||||
visitTopLevelDeclarations(sourceFile, (node) => {
|
|
||||||
if (isDeclaration(node) && node.name) {
|
|
||||||
if (node.name.text === typeName) {
|
|
||||||
result = node;
|
|
||||||
return true /*stop*/;
|
|
||||||
}
|
|
||||||
return false /*continue*/;
|
|
||||||
}
|
|
||||||
// node is ts.VariableStatement
|
|
||||||
if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) {
|
|
||||||
result = node;
|
|
||||||
return true /*stop*/;
|
|
||||||
}
|
|
||||||
return false /*continue*/;
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
function getNodeText(sourceFile, node) {
|
|
||||||
return sourceFile.getFullText().substring(node.pos, node.end);
|
|
||||||
}
|
|
||||||
function hasModifier(modifiers, kind) {
|
|
||||||
if (modifiers) {
|
|
||||||
for (let i = 0; i < modifiers.length; i++) {
|
|
||||||
let mod = modifiers[i];
|
|
||||||
if (mod.kind === kind) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
function isStatic(member) {
|
|
||||||
return hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword);
|
|
||||||
}
|
|
||||||
function isDefaultExport(declaration) {
|
|
||||||
return (hasModifier(declaration.modifiers, ts.SyntaxKind.DefaultKeyword)
|
|
||||||
&& hasModifier(declaration.modifiers, ts.SyntaxKind.ExportKeyword));
|
|
||||||
}
|
|
||||||
function getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums) {
|
|
||||||
let result = getNodeText(sourceFile, declaration);
|
|
||||||
if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) {
|
|
||||||
let interfaceDeclaration = declaration;
|
|
||||||
const staticTypeName = (isDefaultExport(interfaceDeclaration)
|
|
||||||
? `${importName}.default`
|
|
||||||
: `${importName}.${declaration.name.text}`);
|
|
||||||
let instanceTypeName = staticTypeName;
|
|
||||||
const typeParametersCnt = (interfaceDeclaration.typeParameters ? interfaceDeclaration.typeParameters.length : 0);
|
|
||||||
if (typeParametersCnt > 0) {
|
|
||||||
let arr = [];
|
|
||||||
for (let i = 0; i < typeParametersCnt; i++) {
|
|
||||||
arr.push('any');
|
|
||||||
}
|
|
||||||
instanceTypeName = `${instanceTypeName}<${arr.join(',')}>`;
|
|
||||||
}
|
|
||||||
const members = interfaceDeclaration.members;
|
|
||||||
members.forEach((member) => {
|
|
||||||
try {
|
|
||||||
let memberText = getNodeText(sourceFile, member);
|
|
||||||
if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) {
|
|
||||||
result = result.replace(memberText, '');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const memberName = member.name.text;
|
|
||||||
const memberAccess = (memberName.indexOf('.') >= 0 ? `['${memberName}']` : `.${memberName}`);
|
|
||||||
if (isStatic(member)) {
|
|
||||||
usage.push(`a = ${staticTypeName}${memberAccess};`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
usage.push(`a = (<${instanceTypeName}>b)${memberAccess};`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
// life..
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (declaration.kind === ts.SyntaxKind.VariableStatement) {
|
|
||||||
const jsDoc = result.substr(0, declaration.getLeadingTriviaWidth(sourceFile));
|
|
||||||
if (jsDoc.indexOf('@monacodtsreplace') >= 0) {
|
|
||||||
const jsDocLines = jsDoc.split(/\r\n|\r|\n/);
|
|
||||||
let directives = [];
|
|
||||||
for (const jsDocLine of jsDocLines) {
|
|
||||||
const m = jsDocLine.match(/^\s*\* \/([^/]+)\/([^/]+)\/$/);
|
|
||||||
if (m) {
|
|
||||||
directives.push([new RegExp(m[1], 'g'), m[2]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove the jsdoc
|
|
||||||
result = result.substr(jsDoc.length);
|
|
||||||
if (directives.length > 0) {
|
|
||||||
// apply replace directives
|
|
||||||
const replacer = createReplacerFromDirectives(directives);
|
|
||||||
result = replacer(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = result.replace(/export default /g, 'export ');
|
|
||||||
result = result.replace(/export declare /g, 'export ');
|
|
||||||
result = result.replace(/declare /g, '');
|
|
||||||
let lines = result.split(/\r\n|\r|\n/);
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
|
||||||
if (/\s*\*/.test(lines[i])) {
|
|
||||||
// very likely a comment
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
lines[i] = lines[i].replace(/"/g, '\'');
|
|
||||||
}
|
|
||||||
result = lines.join('\n');
|
|
||||||
if (declaration.kind === ts.SyntaxKind.EnumDeclaration) {
|
|
||||||
result = result.replace(/const enum/, 'enum');
|
|
||||||
enums.push({
|
|
||||||
enumName: declaration.name.getText(sourceFile),
|
|
||||||
text: result
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
function format(text, endl) {
|
|
||||||
const REALLY_FORMAT = false;
|
|
||||||
text = preformat(text, endl);
|
|
||||||
if (!REALLY_FORMAT) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
// Parse the source text
|
|
||||||
let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);
|
|
||||||
// Get the formatting edits on the input sources
|
|
||||||
let edits = ts.formatting.formatDocument(sourceFile, getRuleProvider(tsfmt), tsfmt);
|
|
||||||
// Apply the edits on the input code
|
|
||||||
return applyEdits(text, edits);
|
|
||||||
function countParensCurly(text) {
|
|
||||||
let cnt = 0;
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
if (text.charAt(i) === '(' || text.charAt(i) === '{') {
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
if (text.charAt(i) === ')' || text.charAt(i) === '}') {
|
|
||||||
cnt--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
function repeatStr(s, cnt) {
|
|
||||||
let r = '';
|
|
||||||
for (let i = 0; i < cnt; i++) {
|
|
||||||
r += s;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
function preformat(text, endl) {
|
|
||||||
let lines = text.split(endl);
|
|
||||||
let inComment = false;
|
|
||||||
let inCommentDeltaIndent = 0;
|
|
||||||
let indent = 0;
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
|
||||||
let line = lines[i].replace(/\s$/, '');
|
|
||||||
let repeat = false;
|
|
||||||
let lineIndent = 0;
|
|
||||||
do {
|
|
||||||
repeat = false;
|
|
||||||
if (line.substring(0, 4) === ' ') {
|
|
||||||
line = line.substring(4);
|
|
||||||
lineIndent++;
|
|
||||||
repeat = true;
|
|
||||||
}
|
|
||||||
if (line.charAt(0) === '\t') {
|
|
||||||
line = line.substring(1);
|
|
||||||
lineIndent++;
|
|
||||||
repeat = true;
|
|
||||||
}
|
|
||||||
} while (repeat);
|
|
||||||
if (line.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inComment) {
|
|
||||||
if (/\*\//.test(line)) {
|
|
||||||
inComment = false;
|
|
||||||
}
|
|
||||||
lines[i] = repeatStr('\t', lineIndent + inCommentDeltaIndent) + line;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (/\/\*/.test(line)) {
|
|
||||||
inComment = true;
|
|
||||||
inCommentDeltaIndent = indent - lineIndent;
|
|
||||||
lines[i] = repeatStr('\t', indent) + line;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const cnt = countParensCurly(line);
|
|
||||||
let shouldUnindentAfter = false;
|
|
||||||
let shouldUnindentBefore = false;
|
|
||||||
if (cnt < 0) {
|
|
||||||
if (/[({]/.test(line)) {
|
|
||||||
shouldUnindentAfter = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
shouldUnindentBefore = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (cnt === 0) {
|
|
||||||
shouldUnindentBefore = /^\}/.test(line);
|
|
||||||
}
|
|
||||||
let shouldIndentAfter = false;
|
|
||||||
if (cnt > 0) {
|
|
||||||
shouldIndentAfter = true;
|
|
||||||
}
|
|
||||||
else if (cnt === 0) {
|
|
||||||
shouldIndentAfter = /{$/.test(line);
|
|
||||||
}
|
|
||||||
if (shouldUnindentBefore) {
|
|
||||||
indent--;
|
|
||||||
}
|
|
||||||
lines[i] = repeatStr('\t', indent) + line;
|
|
||||||
if (shouldUnindentAfter) {
|
|
||||||
indent--;
|
|
||||||
}
|
|
||||||
if (shouldIndentAfter) {
|
|
||||||
indent++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lines.join(endl);
|
|
||||||
}
|
|
||||||
function getRuleProvider(options) {
|
|
||||||
// Share this between multiple formatters using the same options.
|
|
||||||
// This represents the bulk of the space the formatter uses.
|
|
||||||
return ts.formatting.getFormatContext(options);
|
|
||||||
}
|
|
||||||
function applyEdits(text, edits) {
|
|
||||||
// Apply edits in reverse on the existing text
|
|
||||||
let result = text;
|
|
||||||
for (let i = edits.length - 1; i >= 0; i--) {
|
|
||||||
let change = edits[i];
|
|
||||||
let head = result.slice(0, change.span.start);
|
|
||||||
let tail = result.slice(change.span.start + change.span.length);
|
|
||||||
result = head + change.newText + tail;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function createReplacerFromDirectives(directives) {
|
|
||||||
return (str) => {
|
|
||||||
for (let i = 0; i < directives.length; i++) {
|
|
||||||
str = str.replace(directives[i][0], directives[i][1]);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createReplacer(data) {
|
|
||||||
data = data || '';
|
|
||||||
let rawDirectives = data.split(';');
|
|
||||||
let directives = [];
|
|
||||||
rawDirectives.forEach((rawDirective) => {
|
|
||||||
if (rawDirective.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let pieces = rawDirective.split('=>');
|
|
||||||
let findStr = pieces[0];
|
|
||||||
let replaceStr = pieces[1];
|
|
||||||
findStr = findStr.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
|
|
||||||
findStr = '\\b' + findStr + '\\b';
|
|
||||||
directives.push([new RegExp(findStr, 'g'), replaceStr]);
|
|
||||||
});
|
|
||||||
return createReplacerFromDirectives(directives);
|
|
||||||
}
|
|
||||||
function generateDeclarationFile(recipe, sourceFileGetter) {
|
|
||||||
const endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
|
|
||||||
let lines = recipe.split(endl);
|
|
||||||
let result = [];
|
|
||||||
let usageCounter = 0;
|
|
||||||
let usageImports = [];
|
|
||||||
let usage = [];
|
|
||||||
let failed = false;
|
|
||||||
usage.push(`var a: any;`);
|
|
||||||
usage.push(`var b: any;`);
|
|
||||||
const generateUsageImport = (moduleId) => {
|
|
||||||
let importName = 'm' + (++usageCounter);
|
|
||||||
usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`);
|
|
||||||
return importName;
|
|
||||||
};
|
|
||||||
let enums = [];
|
|
||||||
let version = null;
|
|
||||||
lines.forEach(line => {
|
|
||||||
if (failed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let m0 = line.match(/^\/\/dtsv=(\d+)$/);
|
|
||||||
if (m0) {
|
|
||||||
version = m0[1];
|
|
||||||
}
|
|
||||||
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
|
|
||||||
if (m1) {
|
|
||||||
let moduleId = m1[1];
|
|
||||||
const sourceFile = sourceFileGetter(moduleId);
|
|
||||||
if (!sourceFile) {
|
|
||||||
logErr(`While handling ${line}`);
|
|
||||||
logErr(`Cannot find ${moduleId}`);
|
|
||||||
failed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const importName = generateUsageImport(moduleId);
|
|
||||||
let replacer = createReplacer(m1[2]);
|
|
||||||
let typeNames = m1[3].split(/,/);
|
|
||||||
typeNames.forEach((typeName) => {
|
|
||||||
typeName = typeName.trim();
|
|
||||||
if (typeName.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let declaration = getTopLevelDeclaration(sourceFile, typeName);
|
|
||||||
if (!declaration) {
|
|
||||||
logErr(`While handling ${line}`);
|
|
||||||
logErr(`Cannot find ${typeName}`);
|
|
||||||
failed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
|
|
||||||
if (m2) {
|
|
||||||
let moduleId = m2[1];
|
|
||||||
const sourceFile = sourceFileGetter(moduleId);
|
|
||||||
if (!sourceFile) {
|
|
||||||
logErr(`While handling ${line}`);
|
|
||||||
logErr(`Cannot find ${moduleId}`);
|
|
||||||
failed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const importName = generateUsageImport(moduleId);
|
|
||||||
let replacer = createReplacer(m2[2]);
|
|
||||||
let typeNames = m2[3].split(/,/);
|
|
||||||
let typesToExcludeMap = {};
|
|
||||||
let typesToExcludeArr = [];
|
|
||||||
typeNames.forEach((typeName) => {
|
|
||||||
typeName = typeName.trim();
|
|
||||||
if (typeName.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
typesToExcludeMap[typeName] = true;
|
|
||||||
typesToExcludeArr.push(typeName);
|
|
||||||
});
|
|
||||||
getAllTopLevelDeclarations(sourceFile).forEach((declaration) => {
|
|
||||||
if (isDeclaration(declaration) && declaration.name) {
|
|
||||||
if (typesToExcludeMap[declaration.name.text]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// node is ts.VariableStatement
|
|
||||||
let nodeText = getNodeText(sourceFile, declaration);
|
|
||||||
for (let i = 0; i < typesToExcludeArr.length; i++) {
|
|
||||||
if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result.push(line);
|
|
||||||
});
|
|
||||||
if (failed) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (version !== dtsv) {
|
|
||||||
if (!version) {
|
|
||||||
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let resultTxt = result.join(endl);
|
|
||||||
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
|
|
||||||
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
|
|
||||||
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
resultTxt = format(resultTxt, endl);
|
|
||||||
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
enums.sort((e1, e2) => {
|
|
||||||
if (e1.enumName < e2.enumName) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (e1.enumName > e2.enumName) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
let resultEnums = [
|
|
||||||
'/*---------------------------------------------------------------------------------------------',
|
|
||||||
' * Copyright (c) Microsoft Corporation. All rights reserved.',
|
|
||||||
' * Licensed under the Source EULA. See License.txt in the project root for license information.',
|
|
||||||
' *--------------------------------------------------------------------------------------------*/',
|
|
||||||
'',
|
|
||||||
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
|
|
||||||
''
|
|
||||||
].concat(enums.map(e => e.text)).join(endl);
|
|
||||||
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
resultEnums = format(resultEnums, endl);
|
|
||||||
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
return {
|
|
||||||
result: resultTxt,
|
|
||||||
usageContent: `${usageImports.join('\n')}\n\n${usage.join('\n')}`,
|
|
||||||
enums: resultEnums
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function _run(sourceFileGetter) {
|
|
||||||
const recipe = fs.readFileSync(exports.RECIPE_PATH).toString();
|
|
||||||
const t = generateDeclarationFile(recipe, sourceFileGetter);
|
|
||||||
if (!t) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const result = t.result;
|
|
||||||
const usageContent = t.usageContent;
|
|
||||||
const enums = t.enums;
|
|
||||||
const currentContent = fs.readFileSync(DECLARATION_PATH).toString();
|
|
||||||
const one = currentContent.replace(/\r\n/gm, '\n');
|
|
||||||
const other = result.replace(/\r\n/gm, '\n');
|
|
||||||
const isTheSame = (one === other);
|
|
||||||
return {
|
|
||||||
content: result,
|
|
||||||
usageContent: usageContent,
|
|
||||||
enums: enums,
|
|
||||||
filePath: DECLARATION_PATH,
|
|
||||||
isTheSame
|
|
||||||
};
|
|
||||||
}
|
|
||||||
class FSProvider {
|
|
||||||
existsSync(filePath) {
|
|
||||||
return fs.existsSync(filePath);
|
|
||||||
}
|
|
||||||
statSync(filePath) {
|
|
||||||
return fs.statSync(filePath);
|
|
||||||
}
|
|
||||||
readFileSync(_moduleId, filePath) {
|
|
||||||
return fs.readFileSync(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.FSProvider = FSProvider;
|
|
||||||
class CacheEntry {
|
|
||||||
constructor(sourceFile, mtime) {
|
|
||||||
this.sourceFile = sourceFile;
|
|
||||||
this.mtime = mtime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class DeclarationResolver {
|
|
||||||
constructor(_fsProvider) {
|
|
||||||
this._fsProvider = _fsProvider;
|
|
||||||
this._sourceFileCache = Object.create(null);
|
|
||||||
}
|
|
||||||
invalidateCache(moduleId) {
|
|
||||||
this._sourceFileCache[moduleId] = null;
|
|
||||||
}
|
|
||||||
getDeclarationSourceFile(moduleId) {
|
|
||||||
if (this._sourceFileCache[moduleId]) {
|
|
||||||
// Since we cannot trust file watching to invalidate the cache, check also the mtime
|
|
||||||
const fileName = this._getFileName(moduleId);
|
|
||||||
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
|
|
||||||
if (this._sourceFileCache[moduleId].mtime !== mtime) {
|
|
||||||
this._sourceFileCache[moduleId] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this._sourceFileCache[moduleId]) {
|
|
||||||
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
|
|
||||||
}
|
|
||||||
return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId].sourceFile : null;
|
|
||||||
}
|
|
||||||
_getFileName(moduleId) {
|
|
||||||
if (/\.d\.ts$/.test(moduleId)) {
|
|
||||||
return path.join(SRC, moduleId);
|
|
||||||
}
|
|
||||||
return path.join(SRC, `${moduleId}.ts`);
|
|
||||||
}
|
|
||||||
_getDeclarationSourceFile(moduleId) {
|
|
||||||
const fileName = this._getFileName(moduleId);
|
|
||||||
if (!this._fsProvider.existsSync(fileName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
|
|
||||||
if (/\.d\.ts$/.test(moduleId)) {
|
|
||||||
// const mtime = this._fsProvider.statFileSync()
|
|
||||||
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
|
|
||||||
return new CacheEntry(ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5), mtime);
|
|
||||||
}
|
|
||||||
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
|
|
||||||
const fileMap = {
|
|
||||||
'file.ts': fileContents
|
|
||||||
};
|
|
||||||
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
|
|
||||||
const text = service.getEmitOutput('file.ts', true, true).outputFiles[0].text;
|
|
||||||
return new CacheEntry(ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5), mtime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.DeclarationResolver = DeclarationResolver;
|
|
||||||
function run3(resolver) {
|
|
||||||
const sourceFileGetter = (moduleId) => resolver.getDeclarationSourceFile(moduleId);
|
|
||||||
return _run(sourceFileGetter);
|
|
||||||
}
|
|
||||||
exports.run3 = run3;
|
|
||||||
class TypeScriptLanguageServiceHost {
|
|
||||||
constructor(libs, files, compilerOptions) {
|
|
||||||
this._libs = libs;
|
|
||||||
this._files = files;
|
|
||||||
this._compilerOptions = compilerOptions;
|
|
||||||
}
|
|
||||||
// {{SQL CARBON EDIT}} - provide missing methods
|
|
||||||
readFile() {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
fileExists() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// --- language service host ---------------
|
|
||||||
getCompilationSettings() {
|
|
||||||
return this._compilerOptions;
|
|
||||||
}
|
|
||||||
getScriptFileNames() {
|
|
||||||
return ([]
|
|
||||||
.concat(Object.keys(this._libs))
|
|
||||||
.concat(Object.keys(this._files)));
|
|
||||||
}
|
|
||||||
getScriptVersion(_fileName) {
|
|
||||||
return '1';
|
|
||||||
}
|
|
||||||
getProjectVersion() {
|
|
||||||
return '1';
|
|
||||||
}
|
|
||||||
getScriptSnapshot(fileName) {
|
|
||||||
if (this._files.hasOwnProperty(fileName)) {
|
|
||||||
return ts.ScriptSnapshot.fromString(this._files[fileName]);
|
|
||||||
}
|
|
||||||
else if (this._libs.hasOwnProperty(fileName)) {
|
|
||||||
return ts.ScriptSnapshot.fromString(this._libs[fileName]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ts.ScriptSnapshot.fromString('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getScriptKind(_fileName) {
|
|
||||||
return ts.ScriptKind.TS;
|
|
||||||
}
|
|
||||||
getCurrentDirectory() {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
getDefaultLibFileName(_options) {
|
|
||||||
return 'defaultLib:es5';
|
|
||||||
}
|
|
||||||
isDefaultLibFileName(fileName) {
|
|
||||||
return fileName === this.getDefaultLibFileName(this._compilerOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function execute() {
|
|
||||||
let r = run3(new DeclarationResolver(new FSProvider()));
|
|
||||||
if (!r) {
|
|
||||||
throw new Error(`monaco.d.ts generation error - Cannot continue`);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
exports.execute = execute;
|
|
||||||
@@ -1,757 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as ts from 'typescript';
|
|
||||||
import * as path from 'path';
|
|
||||||
import * as fancyLog from 'fancy-log';
|
|
||||||
import * as ansiColors from 'ansi-colors';
|
|
||||||
|
|
||||||
const dtsv = '3';
|
|
||||||
|
|
||||||
const tsfmt = require('../../tsfmt.json');
|
|
||||||
|
|
||||||
const SRC = path.join(__dirname, '../../src');
|
|
||||||
export const RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe');
|
|
||||||
const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts');
|
|
||||||
|
|
||||||
function logErr(message: any, ...rest: any[]): void {
|
|
||||||
fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest);
|
|
||||||
}
|
|
||||||
|
|
||||||
type SourceFileGetter = (moduleId: string) => ts.SourceFile | null;
|
|
||||||
|
|
||||||
type TSTopLevelDeclaration = ts.InterfaceDeclaration | ts.EnumDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration | ts.FunctionDeclaration | ts.ModuleDeclaration;
|
|
||||||
type TSTopLevelDeclare = TSTopLevelDeclaration | ts.VariableStatement;
|
|
||||||
|
|
||||||
function isDeclaration(a: TSTopLevelDeclare): a is TSTopLevelDeclaration {
|
|
||||||
return (
|
|
||||||
a.kind === ts.SyntaxKind.InterfaceDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.EnumDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.ClassDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.TypeAliasDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.FunctionDeclaration
|
|
||||||
|| a.kind === ts.SyntaxKind.ModuleDeclaration
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function visitTopLevelDeclarations(sourceFile: ts.SourceFile, visitor: (node: TSTopLevelDeclare) => boolean): void {
|
|
||||||
let stop = false;
|
|
||||||
|
|
||||||
let visit = (node: ts.Node): void => {
|
|
||||||
if (stop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (node.kind) {
|
|
||||||
case ts.SyntaxKind.InterfaceDeclaration:
|
|
||||||
case ts.SyntaxKind.EnumDeclaration:
|
|
||||||
case ts.SyntaxKind.ClassDeclaration:
|
|
||||||
case ts.SyntaxKind.VariableStatement:
|
|
||||||
case ts.SyntaxKind.TypeAliasDeclaration:
|
|
||||||
case ts.SyntaxKind.FunctionDeclaration:
|
|
||||||
case ts.SyntaxKind.ModuleDeclaration:
|
|
||||||
stop = visitor(<TSTopLevelDeclare>node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ts.forEachChild(node, visit);
|
|
||||||
};
|
|
||||||
|
|
||||||
visit(sourceFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getAllTopLevelDeclarations(sourceFile: ts.SourceFile): TSTopLevelDeclare[] {
|
|
||||||
let all: TSTopLevelDeclare[] = [];
|
|
||||||
visitTopLevelDeclarations(sourceFile, (node) => {
|
|
||||||
if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) {
|
|
||||||
let interfaceDeclaration = <ts.InterfaceDeclaration>node;
|
|
||||||
let triviaStart = interfaceDeclaration.pos;
|
|
||||||
let triviaEnd = interfaceDeclaration.name.pos;
|
|
||||||
let triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd });
|
|
||||||
|
|
||||||
if (triviaText.indexOf('@internal') === -1) {
|
|
||||||
all.push(node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let nodeText = getNodeText(sourceFile, node);
|
|
||||||
if (nodeText.indexOf('@internal') === -1) {
|
|
||||||
all.push(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false /*continue*/;
|
|
||||||
});
|
|
||||||
return all;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getTopLevelDeclaration(sourceFile: ts.SourceFile, typeName: string): TSTopLevelDeclare | null {
|
|
||||||
let result: TSTopLevelDeclare | null = null;
|
|
||||||
visitTopLevelDeclarations(sourceFile, (node) => {
|
|
||||||
if (isDeclaration(node) && node.name) {
|
|
||||||
if (node.name.text === typeName) {
|
|
||||||
result = node;
|
|
||||||
return true /*stop*/;
|
|
||||||
}
|
|
||||||
return false /*continue*/;
|
|
||||||
}
|
|
||||||
// node is ts.VariableStatement
|
|
||||||
if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) {
|
|
||||||
result = node;
|
|
||||||
return true /*stop*/;
|
|
||||||
}
|
|
||||||
return false /*continue*/;
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getNodeText(sourceFile: ts.SourceFile, node: { pos: number; end: number; }): string {
|
|
||||||
return sourceFile.getFullText().substring(node.pos, node.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasModifier(modifiers: ts.NodeArray<ts.Modifier> | undefined, kind: ts.SyntaxKind): boolean {
|
|
||||||
if (modifiers) {
|
|
||||||
for (let i = 0; i < modifiers.length; i++) {
|
|
||||||
let mod = modifiers[i];
|
|
||||||
if (mod.kind === kind) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isStatic(member: ts.ClassElement | ts.TypeElement): boolean {
|
|
||||||
return hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDefaultExport(declaration: ts.InterfaceDeclaration | ts.ClassDeclaration): boolean {
|
|
||||||
return (
|
|
||||||
hasModifier(declaration.modifiers, ts.SyntaxKind.DefaultKeyword)
|
|
||||||
&& hasModifier(declaration.modifiers, ts.SyntaxKind.ExportKeyword)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMassagedTopLevelDeclarationText(sourceFile: ts.SourceFile, declaration: TSTopLevelDeclare, importName: string, usage: string[], enums: IEnumEntry[]): string {
|
|
||||||
let result = getNodeText(sourceFile, declaration);
|
|
||||||
if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) {
|
|
||||||
let interfaceDeclaration = <ts.InterfaceDeclaration | ts.ClassDeclaration>declaration;
|
|
||||||
|
|
||||||
const staticTypeName = (
|
|
||||||
isDefaultExport(interfaceDeclaration)
|
|
||||||
? `${importName}.default`
|
|
||||||
: `${importName}.${declaration.name!.text}`
|
|
||||||
);
|
|
||||||
|
|
||||||
let instanceTypeName = staticTypeName;
|
|
||||||
const typeParametersCnt = (interfaceDeclaration.typeParameters ? interfaceDeclaration.typeParameters.length : 0);
|
|
||||||
if (typeParametersCnt > 0) {
|
|
||||||
let arr: string[] = [];
|
|
||||||
for (let i = 0; i < typeParametersCnt; i++) {
|
|
||||||
arr.push('any');
|
|
||||||
}
|
|
||||||
instanceTypeName = `${instanceTypeName}<${arr.join(',')}>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const members: ts.NodeArray<ts.ClassElement | ts.TypeElement> = interfaceDeclaration.members;
|
|
||||||
members.forEach((member) => {
|
|
||||||
try {
|
|
||||||
let memberText = getNodeText(sourceFile, member);
|
|
||||||
if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) {
|
|
||||||
result = result.replace(memberText, '');
|
|
||||||
} else {
|
|
||||||
const memberName = (<ts.Identifier | ts.StringLiteral>member.name).text;
|
|
||||||
const memberAccess = (memberName.indexOf('.') >= 0 ? `['${memberName}']` : `.${memberName}`);
|
|
||||||
if (isStatic(member)) {
|
|
||||||
usage.push(`a = ${staticTypeName}${memberAccess};`);
|
|
||||||
} else {
|
|
||||||
usage.push(`a = (<${instanceTypeName}>b)${memberAccess};`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// life..
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (declaration.kind === ts.SyntaxKind.VariableStatement) {
|
|
||||||
const jsDoc = result.substr(0, declaration.getLeadingTriviaWidth(sourceFile));
|
|
||||||
if (jsDoc.indexOf('@monacodtsreplace') >= 0) {
|
|
||||||
const jsDocLines = jsDoc.split(/\r\n|\r|\n/);
|
|
||||||
let directives: [RegExp, string][] = [];
|
|
||||||
for (const jsDocLine of jsDocLines) {
|
|
||||||
const m = jsDocLine.match(/^\s*\* \/([^/]+)\/([^/]+)\/$/);
|
|
||||||
if (m) {
|
|
||||||
directives.push([new RegExp(m[1], 'g'), m[2]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove the jsdoc
|
|
||||||
result = result.substr(jsDoc.length);
|
|
||||||
if (directives.length > 0) {
|
|
||||||
// apply replace directives
|
|
||||||
const replacer = createReplacerFromDirectives(directives);
|
|
||||||
result = replacer(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = result.replace(/export default /g, 'export ');
|
|
||||||
result = result.replace(/export declare /g, 'export ');
|
|
||||||
result = result.replace(/declare /g, '');
|
|
||||||
let lines = result.split(/\r\n|\r|\n/);
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
|
||||||
if (/\s*\*/.test(lines[i])) {
|
|
||||||
// very likely a comment
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
lines[i] = lines[i].replace(/"/g, '\'');
|
|
||||||
}
|
|
||||||
result = lines.join('\n');
|
|
||||||
|
|
||||||
if (declaration.kind === ts.SyntaxKind.EnumDeclaration) {
|
|
||||||
result = result.replace(/const enum/, 'enum');
|
|
||||||
enums.push({
|
|
||||||
enumName: declaration.name.getText(sourceFile),
|
|
||||||
text: result
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function format(text: string, endl: string): string {
|
|
||||||
const REALLY_FORMAT = false;
|
|
||||||
|
|
||||||
text = preformat(text, endl);
|
|
||||||
if (!REALLY_FORMAT) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the source text
|
|
||||||
let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);
|
|
||||||
|
|
||||||
// Get the formatting edits on the input sources
|
|
||||||
let edits = (<any>ts).formatting.formatDocument(sourceFile, getRuleProvider(tsfmt), tsfmt);
|
|
||||||
|
|
||||||
// Apply the edits on the input code
|
|
||||||
return applyEdits(text, edits);
|
|
||||||
|
|
||||||
function countParensCurly(text: string): number {
|
|
||||||
let cnt = 0;
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
if (text.charAt(i) === '(' || text.charAt(i) === '{') {
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
if (text.charAt(i) === ')' || text.charAt(i) === '}') {
|
|
||||||
cnt--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
function repeatStr(s: string, cnt: number): string {
|
|
||||||
let r = '';
|
|
||||||
for (let i = 0; i < cnt; i++) {
|
|
||||||
r += s;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
function preformat(text: string, endl: string): string {
|
|
||||||
let lines = text.split(endl);
|
|
||||||
let inComment = false;
|
|
||||||
let inCommentDeltaIndent = 0;
|
|
||||||
let indent = 0;
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
|
||||||
let line = lines[i].replace(/\s$/, '');
|
|
||||||
let repeat = false;
|
|
||||||
let lineIndent = 0;
|
|
||||||
do {
|
|
||||||
repeat = false;
|
|
||||||
if (line.substring(0, 4) === ' ') {
|
|
||||||
line = line.substring(4);
|
|
||||||
lineIndent++;
|
|
||||||
repeat = true;
|
|
||||||
}
|
|
||||||
if (line.charAt(0) === '\t') {
|
|
||||||
line = line.substring(1);
|
|
||||||
lineIndent++;
|
|
||||||
repeat = true;
|
|
||||||
}
|
|
||||||
} while (repeat);
|
|
||||||
|
|
||||||
if (line.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inComment) {
|
|
||||||
if (/\*\//.test(line)) {
|
|
||||||
inComment = false;
|
|
||||||
}
|
|
||||||
lines[i] = repeatStr('\t', lineIndent + inCommentDeltaIndent) + line;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/\/\*/.test(line)) {
|
|
||||||
inComment = true;
|
|
||||||
inCommentDeltaIndent = indent - lineIndent;
|
|
||||||
lines[i] = repeatStr('\t', indent) + line;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cnt = countParensCurly(line);
|
|
||||||
let shouldUnindentAfter = false;
|
|
||||||
let shouldUnindentBefore = false;
|
|
||||||
if (cnt < 0) {
|
|
||||||
if (/[({]/.test(line)) {
|
|
||||||
shouldUnindentAfter = true;
|
|
||||||
} else {
|
|
||||||
shouldUnindentBefore = true;
|
|
||||||
}
|
|
||||||
} else if (cnt === 0) {
|
|
||||||
shouldUnindentBefore = /^\}/.test(line);
|
|
||||||
}
|
|
||||||
let shouldIndentAfter = false;
|
|
||||||
if (cnt > 0) {
|
|
||||||
shouldIndentAfter = true;
|
|
||||||
} else if (cnt === 0) {
|
|
||||||
shouldIndentAfter = /{$/.test(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldUnindentBefore) {
|
|
||||||
indent--;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines[i] = repeatStr('\t', indent) + line;
|
|
||||||
|
|
||||||
if (shouldUnindentAfter) {
|
|
||||||
indent--;
|
|
||||||
}
|
|
||||||
if (shouldIndentAfter) {
|
|
||||||
indent++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lines.join(endl);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRuleProvider(options: ts.FormatCodeSettings) {
|
|
||||||
// Share this between multiple formatters using the same options.
|
|
||||||
// This represents the bulk of the space the formatter uses.
|
|
||||||
return (ts as any).formatting.getFormatContext(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyEdits(text: string, edits: ts.TextChange[]): string {
|
|
||||||
// Apply edits in reverse on the existing text
|
|
||||||
let result = text;
|
|
||||||
for (let i = edits.length - 1; i >= 0; i--) {
|
|
||||||
let change = edits[i];
|
|
||||||
let head = result.slice(0, change.span.start);
|
|
||||||
let tail = result.slice(change.span.start + change.span.length);
|
|
||||||
result = head + change.newText + tail;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createReplacerFromDirectives(directives: [RegExp, string][]): (str: string) => string {
|
|
||||||
return (str: string) => {
|
|
||||||
for (let i = 0; i < directives.length; i++) {
|
|
||||||
str = str.replace(directives[i][0], directives[i][1]);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createReplacer(data: string): (str: string) => string {
|
|
||||||
data = data || '';
|
|
||||||
let rawDirectives = data.split(';');
|
|
||||||
let directives: [RegExp, string][] = [];
|
|
||||||
rawDirectives.forEach((rawDirective) => {
|
|
||||||
if (rawDirective.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let pieces = rawDirective.split('=>');
|
|
||||||
let findStr = pieces[0];
|
|
||||||
let replaceStr = pieces[1];
|
|
||||||
|
|
||||||
findStr = findStr.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
|
|
||||||
findStr = '\\b' + findStr + '\\b';
|
|
||||||
directives.push([new RegExp(findStr, 'g'), replaceStr]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return createReplacerFromDirectives(directives);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ITempResult {
|
|
||||||
result: string;
|
|
||||||
usageContent: string;
|
|
||||||
enums: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IEnumEntry {
|
|
||||||
enumName: string;
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateDeclarationFile(recipe: string, sourceFileGetter: SourceFileGetter): ITempResult | null {
|
|
||||||
const endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
|
|
||||||
|
|
||||||
let lines = recipe.split(endl);
|
|
||||||
let result: string[] = [];
|
|
||||||
|
|
||||||
let usageCounter = 0;
|
|
||||||
let usageImports: string[] = [];
|
|
||||||
let usage: string[] = [];
|
|
||||||
|
|
||||||
let failed = false;
|
|
||||||
|
|
||||||
usage.push(`var a: any;`);
|
|
||||||
usage.push(`var b: any;`);
|
|
||||||
|
|
||||||
const generateUsageImport = (moduleId: string) => {
|
|
||||||
let importName = 'm' + (++usageCounter);
|
|
||||||
usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`);
|
|
||||||
return importName;
|
|
||||||
};
|
|
||||||
|
|
||||||
let enums: IEnumEntry[] = [];
|
|
||||||
let version: string | null = null;
|
|
||||||
|
|
||||||
lines.forEach(line => {
|
|
||||||
|
|
||||||
if (failed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let m0 = line.match(/^\/\/dtsv=(\d+)$/);
|
|
||||||
if (m0) {
|
|
||||||
version = m0[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
|
|
||||||
if (m1) {
|
|
||||||
let moduleId = m1[1];
|
|
||||||
const sourceFile = sourceFileGetter(moduleId);
|
|
||||||
if (!sourceFile) {
|
|
||||||
logErr(`While handling ${line}`);
|
|
||||||
logErr(`Cannot find ${moduleId}`);
|
|
||||||
failed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const importName = generateUsageImport(moduleId);
|
|
||||||
|
|
||||||
let replacer = createReplacer(m1[2]);
|
|
||||||
|
|
||||||
let typeNames = m1[3].split(/,/);
|
|
||||||
typeNames.forEach((typeName) => {
|
|
||||||
typeName = typeName.trim();
|
|
||||||
if (typeName.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let declaration = getTopLevelDeclaration(sourceFile, typeName);
|
|
||||||
if (!declaration) {
|
|
||||||
logErr(`While handling ${line}`);
|
|
||||||
logErr(`Cannot find ${typeName}`);
|
|
||||||
failed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
|
|
||||||
if (m2) {
|
|
||||||
let moduleId = m2[1];
|
|
||||||
const sourceFile = sourceFileGetter(moduleId);
|
|
||||||
if (!sourceFile) {
|
|
||||||
logErr(`While handling ${line}`);
|
|
||||||
logErr(`Cannot find ${moduleId}`);
|
|
||||||
failed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const importName = generateUsageImport(moduleId);
|
|
||||||
|
|
||||||
let replacer = createReplacer(m2[2]);
|
|
||||||
|
|
||||||
let typeNames = m2[3].split(/,/);
|
|
||||||
let typesToExcludeMap: { [typeName: string]: boolean; } = {};
|
|
||||||
let typesToExcludeArr: string[] = [];
|
|
||||||
typeNames.forEach((typeName) => {
|
|
||||||
typeName = typeName.trim();
|
|
||||||
if (typeName.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
typesToExcludeMap[typeName] = true;
|
|
||||||
typesToExcludeArr.push(typeName);
|
|
||||||
});
|
|
||||||
|
|
||||||
getAllTopLevelDeclarations(sourceFile).forEach((declaration) => {
|
|
||||||
if (isDeclaration(declaration) && declaration.name) {
|
|
||||||
if (typesToExcludeMap[declaration.name.text]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// node is ts.VariableStatement
|
|
||||||
let nodeText = getNodeText(sourceFile, declaration);
|
|
||||||
for (let i = 0; i < typesToExcludeArr.length; i++) {
|
|
||||||
if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push(line);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (failed) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version !== dtsv) {
|
|
||||||
if (!version) {
|
|
||||||
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
|
|
||||||
} else {
|
|
||||||
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let resultTxt = result.join(endl);
|
|
||||||
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
|
|
||||||
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
|
|
||||||
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
resultTxt = format(resultTxt, endl);
|
|
||||||
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
|
|
||||||
enums.sort((e1, e2) => {
|
|
||||||
if (e1.enumName < e2.enumName) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (e1.enumName > e2.enumName) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
let resultEnums = [
|
|
||||||
'/*---------------------------------------------------------------------------------------------',
|
|
||||||
' * Copyright (c) Microsoft Corporation. All rights reserved.',
|
|
||||||
' * Licensed under the Source EULA. See License.txt in the project root for license information.',
|
|
||||||
' *--------------------------------------------------------------------------------------------*/',
|
|
||||||
'',
|
|
||||||
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
|
|
||||||
''
|
|
||||||
].concat(enums.map(e => e.text)).join(endl);
|
|
||||||
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
resultEnums = format(resultEnums, endl);
|
|
||||||
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
|
|
||||||
|
|
||||||
return {
|
|
||||||
result: resultTxt,
|
|
||||||
usageContent: `${usageImports.join('\n')}\n\n${usage.join('\n')}`,
|
|
||||||
enums: resultEnums
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IMonacoDeclarationResult {
|
|
||||||
content: string;
|
|
||||||
usageContent: string;
|
|
||||||
enums: string;
|
|
||||||
filePath: string;
|
|
||||||
isTheSame: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _run(sourceFileGetter: SourceFileGetter): IMonacoDeclarationResult | null {
|
|
||||||
const recipe = fs.readFileSync(RECIPE_PATH).toString();
|
|
||||||
const t = generateDeclarationFile(recipe, sourceFileGetter);
|
|
||||||
if (!t) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = t.result;
|
|
||||||
const usageContent = t.usageContent;
|
|
||||||
const enums = t.enums;
|
|
||||||
|
|
||||||
const currentContent = fs.readFileSync(DECLARATION_PATH).toString();
|
|
||||||
const one = currentContent.replace(/\r\n/gm, '\n');
|
|
||||||
const other = result.replace(/\r\n/gm, '\n');
|
|
||||||
const isTheSame = (one === other);
|
|
||||||
|
|
||||||
return {
|
|
||||||
content: result,
|
|
||||||
usageContent: usageContent,
|
|
||||||
enums: enums,
|
|
||||||
filePath: DECLARATION_PATH,
|
|
||||||
isTheSame
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FSProvider {
|
|
||||||
public existsSync(filePath: string): boolean {
|
|
||||||
return fs.existsSync(filePath);
|
|
||||||
}
|
|
||||||
public statSync(filePath: string): fs.Stats {
|
|
||||||
return fs.statSync(filePath);
|
|
||||||
}
|
|
||||||
public readFileSync(_moduleId: string, filePath: string): Buffer {
|
|
||||||
return fs.readFileSync(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CacheEntry {
|
|
||||||
constructor(
|
|
||||||
public readonly sourceFile: ts.SourceFile,
|
|
||||||
public readonly mtime: number
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DeclarationResolver {
|
|
||||||
|
|
||||||
private _sourceFileCache: { [moduleId: string]: CacheEntry | null; };
|
|
||||||
|
|
||||||
constructor(private readonly _fsProvider: FSProvider) {
|
|
||||||
this._sourceFileCache = Object.create(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public invalidateCache(moduleId: string): void {
|
|
||||||
this._sourceFileCache[moduleId] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getDeclarationSourceFile(moduleId: string): ts.SourceFile | null {
|
|
||||||
if (this._sourceFileCache[moduleId]) {
|
|
||||||
// Since we cannot trust file watching to invalidate the cache, check also the mtime
|
|
||||||
const fileName = this._getFileName(moduleId);
|
|
||||||
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
|
|
||||||
if (this._sourceFileCache[moduleId]!.mtime !== mtime) {
|
|
||||||
this._sourceFileCache[moduleId] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this._sourceFileCache[moduleId]) {
|
|
||||||
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
|
|
||||||
}
|
|
||||||
return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId]!.sourceFile : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getFileName(moduleId: string): string {
|
|
||||||
if (/\.d\.ts$/.test(moduleId)) {
|
|
||||||
return path.join(SRC, moduleId);
|
|
||||||
}
|
|
||||||
return path.join(SRC, `${moduleId}.ts`);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getDeclarationSourceFile(moduleId: string): CacheEntry | null {
|
|
||||||
const fileName = this._getFileName(moduleId);
|
|
||||||
if (!this._fsProvider.existsSync(fileName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
|
|
||||||
if (/\.d\.ts$/.test(moduleId)) {
|
|
||||||
// const mtime = this._fsProvider.statFileSync()
|
|
||||||
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
|
|
||||||
return new CacheEntry(
|
|
||||||
ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5),
|
|
||||||
mtime
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
|
|
||||||
const fileMap: IFileMap = {
|
|
||||||
'file.ts': fileContents
|
|
||||||
};
|
|
||||||
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
|
|
||||||
const text = service.getEmitOutput('file.ts', true, true).outputFiles[0].text;
|
|
||||||
return new CacheEntry(
|
|
||||||
ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5),
|
|
||||||
mtime
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function run3(resolver: DeclarationResolver): IMonacoDeclarationResult | null {
|
|
||||||
const sourceFileGetter = (moduleId: string) => resolver.getDeclarationSourceFile(moduleId);
|
|
||||||
return _run(sourceFileGetter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface ILibMap { [libName: string]: string; }
|
|
||||||
interface IFileMap { [fileName: string]: string; }
|
|
||||||
|
|
||||||
class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost {
|
|
||||||
|
|
||||||
private readonly _libs: ILibMap;
|
|
||||||
private readonly _files: IFileMap;
|
|
||||||
private readonly _compilerOptions: ts.CompilerOptions;
|
|
||||||
|
|
||||||
constructor(libs: ILibMap, files: IFileMap, compilerOptions: ts.CompilerOptions) {
|
|
||||||
this._libs = libs;
|
|
||||||
this._files = files;
|
|
||||||
this._compilerOptions = compilerOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}} - provide missing methods
|
|
||||||
readFile(): string | undefined {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
fileExists(): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- language service host ---------------
|
|
||||||
|
|
||||||
getCompilationSettings(): ts.CompilerOptions {
|
|
||||||
return this._compilerOptions;
|
|
||||||
}
|
|
||||||
getScriptFileNames(): string[] {
|
|
||||||
return (
|
|
||||||
([] as string[])
|
|
||||||
.concat(Object.keys(this._libs))
|
|
||||||
.concat(Object.keys(this._files))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
getScriptVersion(_fileName: string): string {
|
|
||||||
return '1';
|
|
||||||
}
|
|
||||||
getProjectVersion(): string {
|
|
||||||
return '1';
|
|
||||||
}
|
|
||||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
|
|
||||||
if (this._files.hasOwnProperty(fileName)) {
|
|
||||||
return ts.ScriptSnapshot.fromString(this._files[fileName]);
|
|
||||||
} else if (this._libs.hasOwnProperty(fileName)) {
|
|
||||||
return ts.ScriptSnapshot.fromString(this._libs[fileName]);
|
|
||||||
} else {
|
|
||||||
return ts.ScriptSnapshot.fromString('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getScriptKind(_fileName: string): ts.ScriptKind {
|
|
||||||
return ts.ScriptKind.TS;
|
|
||||||
}
|
|
||||||
getCurrentDirectory(): string {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
getDefaultLibFileName(_options: ts.CompilerOptions): string {
|
|
||||||
return 'defaultLib:es5';
|
|
||||||
}
|
|
||||||
isDefaultLibFileName(fileName: string): boolean {
|
|
||||||
return fileName === this.getDefaultLibFileName(this._compilerOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function execute(): IMonacoDeclarationResult {
|
|
||||||
let r = run3(new DeclarationResolver(new FSProvider()));
|
|
||||||
if (!r) {
|
|
||||||
throw new Error(`monaco.d.ts generation error - Cannot continue`);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
@@ -3,10 +3,11 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@actions/core": "1.2.6",
|
||||||
|
"@actions/github": "2.1.1",
|
||||||
"@azure/cosmos": "^3.14.1",
|
"@azure/cosmos": "^3.14.1",
|
||||||
"@azure/identity": "^2.1.0",
|
"@azure/identity": "^3.1.4",
|
||||||
"@azure/storage-blob": "^12.13.0",
|
"@azure/storage-blob": "^12.13.0",
|
||||||
"@vscode/vsce": "2.16.0",
|
|
||||||
"@electron/get": "^1.12.4",
|
"@electron/get": "^1.12.4",
|
||||||
"@types/ansi-colors": "^3.2.0",
|
"@types/ansi-colors": "^3.2.0",
|
||||||
"@types/azure": "0.9.19",
|
"@types/azure": "0.9.19",
|
||||||
@@ -17,12 +18,12 @@
|
|||||||
"@types/documentdb": "^1.10.5",
|
"@types/documentdb": "^1.10.5",
|
||||||
"@types/eslint": "4.16.1",
|
"@types/eslint": "4.16.1",
|
||||||
"@types/eslint-visitor-keys": "^1.0.0",
|
"@types/eslint-visitor-keys": "^1.0.0",
|
||||||
"@types/fancy-log": "^1.3.1",
|
"@types/fancy-log": "^1.3.0",
|
||||||
"@types/fs-extra": "^9.0.12",
|
"@types/fs-extra": "^9.0.12",
|
||||||
"@types/glob": "^7.1.1",
|
"@types/glob": "^7.1.1",
|
||||||
"@types/gulp": "^4.0.10",
|
"@types/gulp": "^4.0.5",
|
||||||
"@types/gulp-concat": "^0.0.32",
|
"@types/gulp-concat": "^0.0.32",
|
||||||
"@types/gulp-filter": "^3.0.35",
|
"@types/gulp-filter": "^3.0.32",
|
||||||
"@types/gulp-gzip": "^0.0.31",
|
"@types/gulp-gzip": "^0.0.31",
|
||||||
"@types/gulp-json-editor": "^2.2.31",
|
"@types/gulp-json-editor": "^2.2.31",
|
||||||
"@types/gulp-postcss": "^8.0.0",
|
"@types/gulp-postcss": "^8.0.0",
|
||||||
@@ -40,27 +41,29 @@
|
|||||||
"@types/request": "^2.47.0",
|
"@types/request": "^2.47.0",
|
||||||
"@types/rimraf": "^2.0.4",
|
"@types/rimraf": "^2.0.4",
|
||||||
"@types/through": "^0.0.29",
|
"@types/through": "^0.0.29",
|
||||||
"@types/through2": "^2.0.34",
|
"@types/through2": "^2.0.36",
|
||||||
"@types/tmp": "^0.2.1",
|
"@types/tmp": "^0.2.1",
|
||||||
"@types/underscore": "^1.8.9",
|
"@types/underscore": "^1.8.9",
|
||||||
"@types/webpack": "^4.41.25",
|
"@types/webpack": "^4.41.25",
|
||||||
"@types/xml2js": "0.4.11",
|
"@types/xml2js": "0.4.11",
|
||||||
"@typescript-eslint/experimental-utils": "~2.13.0",
|
"@typescript-eslint/experimental-utils": "~5.10.0",
|
||||||
"@typescript-eslint/parser": "^5.10.0",
|
"@typescript-eslint/parser": "^5.10.0",
|
||||||
"@vscode/iconv-lite-umd": "0.7.0",
|
"@vscode/iconv-lite-umd": "0.7.0",
|
||||||
|
"@vscode/vsce": "2.16.0",
|
||||||
"applicationinsights": "1.0.8",
|
"applicationinsights": "1.0.8",
|
||||||
|
"axios": "0.21.4",
|
||||||
"byline": "^5.0.0",
|
"byline": "^5.0.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"commander": "^7.0.0",
|
"commander": "^7.0.0",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"documentdb": "1.13.0",
|
"documentdb": "1.13.0",
|
||||||
"electron-osx-sign": "^0.4.16",
|
"electron-osx-sign": "^0.4.16",
|
||||||
"esbuild": "^0.12.6",
|
"esbuild": "^0.14.2",
|
||||||
"extract-zip": "^2.0.1",
|
"extract-zip": "^2.0.1",
|
||||||
"fs-extra": "^9.1.0",
|
"fs-extra": "^9.1.0",
|
||||||
"got": "11.8.5",
|
"got": "11.8.5",
|
||||||
"gulp-merge-json": "^2.1.1",
|
"gulp-merge-json": "^2.1.1",
|
||||||
"iconv-lite-umd": "0.6.8",
|
"gulp-shell": "^0.8.0",
|
||||||
"jsonc-parser": "^2.3.0",
|
"jsonc-parser": "^2.3.0",
|
||||||
"mime": "^1.4.1",
|
"mime": "^1.4.1",
|
||||||
"mkdirp": "^1.0.4",
|
"mkdirp": "^1.0.4",
|
||||||
@@ -71,23 +74,18 @@
|
|||||||
"rollup-plugin-commonjs": "^10.1.0",
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
"source-map": "0.6.1",
|
"source-map": "0.6.1",
|
||||||
|
"through2": "^4.0.2",
|
||||||
"tmp": "^0.2.1",
|
"tmp": "^0.2.1",
|
||||||
"typescript": "^4.8.0-dev.20220518",
|
|
||||||
"vsce": "2.8.0",
|
|
||||||
"vscode-universal-bundler": "^0.0.2"
|
"vscode-universal-bundler": "^0.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": "tsc -p tsconfig.build.json",
|
"compile": "../node_modules/.bin/tsc -p tsconfig.build.json",
|
||||||
"watch": "tsc -p tsconfig.build.json --watch",
|
"watch": "../node_modules/.bin/tsc -p tsconfig.build.json --watch",
|
||||||
"npmCheckJs": "tsc --noEmit"
|
"npmCheckJs": "../node_modules/.bin/tsc --noEmit"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"tree-sitter": "https://github.com/joaomoreno/node-tree-sitter/releases/download/v0.20.0/tree-sitter-0.20.0.tgz",
|
"tree-sitter": "https://github.com/joaomoreno/node-tree-sitter/releases/download/v0.20.0/tree-sitter-0.20.0.tgz",
|
||||||
"tree-sitter-typescript": "^0.20.1",
|
"tree-sitter-typescript": "^0.20.1",
|
||||||
"vscode-gulp-watch": "^5.0.3"
|
"vscode-gulp-watch": "^5.0.3"
|
||||||
},
|
|
||||||
"resolutions": {
|
|
||||||
"json-schema": "0.4.0",
|
|
||||||
"jsonwebtoken": "9.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"checkJs": false
|
"checkJs": false,
|
||||||
}
|
"noEmit": false
|
||||||
}
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2017",
|
"target": "es2020",
|
||||||
|
"lib": ["ES2020"],
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"alwaysStrict": true,
|
"alwaysStrict": true,
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
@@ -12,19 +13,19 @@
|
|||||||
// use the tsconfig.build.json for compiling which disable JavaScript
|
// use the tsconfig.build.json for compiling which disable JavaScript
|
||||||
// type checking so that JavaScript file are not transpiled
|
// type checking so that JavaScript file are not transpiled
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"exactOptionalPropertyTypes": false,
|
"exactOptionalPropertyTypes": false,
|
||||||
"useUnknownInCatchVariables": false,
|
"useUnknownInCatchVariables": false,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"newLine": "lf"
|
"newLine": "lf",
|
||||||
|
"noEmit": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts"
|
"**/*.ts",
|
||||||
|
"**/*.js"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules/**",
|
"node_modules/**"
|
||||||
"actions/**" // {{SQL CARBON EDIT}}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
859
build/yarn.lock
859
build/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -199,7 +199,8 @@ export function createViewContext(): ViewTestContext {
|
|||||||
data: [] as any[][],
|
data: [] as any[][],
|
||||||
columns: [] as string[],
|
columns: [] as string[],
|
||||||
onRowSelected: onClick.event,
|
onRowSelected: onClick.event,
|
||||||
appendData: (data: any[][]) => undefined,
|
appendData: (_data: any[][]) => undefined,
|
||||||
|
setActiveCell: (_row: number, _column: number) => undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
let loadingComponent: () => azdata.LoadingComponent = () => Object.assign({}, componentBase, {
|
let loadingComponent: () => azdata.LoadingComponent = () => Object.assign({}, componentBase, {
|
||||||
|
|||||||
@@ -301,6 +301,9 @@ export class MockTableComponent extends MockUIComponent implements azdata.TableC
|
|||||||
appendData(data: any[][]): Thenable<void> {
|
appendData(data: any[][]): Thenable<void> {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
setActiveCell(row: number, column: number): void {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MockDeclarativeTableComponent extends MockUIComponent implements azdata.DeclarativeTableComponent {
|
export class MockDeclarativeTableComponent extends MockUIComponent implements azdata.DeclarativeTableComponent {
|
||||||
|
|||||||
52
extensions/import/src/common/utils.ts
Normal file
52
extensions/import/src/common/utils.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
|
const mssqlExtensionConfigName = 'mssql';
|
||||||
|
const enableSqlAuthenticationProviderConfig = 'enableSqlAuthenticationProvider';
|
||||||
|
|
||||||
|
const azureExtensionConfigName = 'azure';
|
||||||
|
const azureAuthenticationLibraryConfig = 'authenticationLibrary';
|
||||||
|
const MSAL = 'MSAL';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns 'True' if MSAL auth library is in use and SQL Auth provider is enabled.
|
||||||
|
*/
|
||||||
|
export function isMssqlAuthProviderEnabled(): boolean {
|
||||||
|
return getAzureAuthenticationLibraryConfig() === MSAL && getEnableSqlAuthenticationProviderConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConfiguration(config: string): vscode.WorkspaceConfiguration {
|
||||||
|
return vscode.workspace.getConfiguration(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads setting 'azure.AuthenticationLibrary' and returns the library name enabled.
|
||||||
|
* @returns MSAL | ADAL
|
||||||
|
*/
|
||||||
|
export function getAzureAuthenticationLibraryConfig(): string {
|
||||||
|
const config = getConfiguration(azureExtensionConfigName);
|
||||||
|
if (config) {
|
||||||
|
return config.get<string>(azureAuthenticationLibraryConfig, MSAL); // default Auth library
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return MSAL; // default Auth library
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads setting 'mssql.enableSqlAuthenticationProvider' and returns true if it's enabled.
|
||||||
|
* @returns True Sql Auth provider is enabled for MSSQL provider.
|
||||||
|
*/
|
||||||
|
export function getEnableSqlAuthenticationProviderConfig(): boolean {
|
||||||
|
const config = getConfiguration(mssqlExtensionConfigName);
|
||||||
|
if (config) {
|
||||||
|
return config.get<boolean>(enableSqlAuthenticationProviderConfig, true); // enabled by default
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true; // enabled by default
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import { ImportPage } from '../api/importPage';
|
|||||||
import { InsertDataResponse } from '../../services/contracts';
|
import { InsertDataResponse } from '../../services/contracts';
|
||||||
import * as constants from '../../common/constants';
|
import * as constants from '../../common/constants';
|
||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
|
import { isMssqlAuthProviderEnabled } from '../../common/utils';
|
||||||
|
|
||||||
export class SummaryPage extends ImportPage {
|
export class SummaryPage extends ImportPage {
|
||||||
private _table: azdata.TableComponent;
|
private _table: azdata.TableComponent;
|
||||||
@@ -137,10 +138,14 @@ export class SummaryPage extends ImportPage {
|
|||||||
|
|
||||||
const currentServer = this.model.server;
|
const currentServer = this.model.server;
|
||||||
const includePasswordInConnectionString = (currentServer.options.authenticationType === azdata.connection.AuthenticationType.Integrated) ? false : true;
|
const includePasswordInConnectionString = (currentServer.options.authenticationType === azdata.connection.AuthenticationType.Integrated) ? false : true;
|
||||||
const connectionString = await azdata.connection.getConnectionString(currentServer.connectionId, includePasswordInConnectionString);
|
let connectionString = await azdata.connection.getConnectionString(currentServer.connectionId, includePasswordInConnectionString);
|
||||||
|
|
||||||
let accessToken = undefined;
|
let accessToken = undefined;
|
||||||
if (currentServer.options.authenticationType === azdata.connection.AuthenticationType.AzureMFA) {
|
if (currentServer.options.authenticationType === azdata.connection.AuthenticationType.AzureMFA) {
|
||||||
|
// Remove authentication properties from connection string if SQL Authentication Provider is enabled
|
||||||
|
if (isMssqlAuthProviderEnabled()) {
|
||||||
|
connectionString = this.updateConnectionStringForAccessToken(connectionString);
|
||||||
|
}
|
||||||
const azureAccount = (await azdata.accounts.getAllAccounts()).filter(v => v.key.accountId === currentServer.options.azureAccount)[0];
|
const azureAccount = (await azdata.accounts.getAllAccounts()).filter(v => v.key.accountId === currentServer.options.azureAccount)[0];
|
||||||
accessToken = (await azdata.accounts.getAccountSecurityToken(azureAccount, currentServer.options.azureTenantId, azdata.AzureResource.Sql)).token;
|
accessToken = (await azdata.accounts.getAccountSecurityToken(azureAccount, currentServer.options.azureTenantId, azdata.AzureResource.Sql)).token;
|
||||||
}
|
}
|
||||||
@@ -178,6 +183,21 @@ export class SummaryPage extends ImportPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes authentication related properties from connection string as SQL Tools Service now supports
|
||||||
|
* 'EnableSqlAuthenticationProvider' which sets the below properties on connection string that conflict with access token:
|
||||||
|
* 1. User Id
|
||||||
|
* 2. Authentication
|
||||||
|
* Since we need to set access token, we cannot use the same connection string as is.
|
||||||
|
* @param connString Connection string to fix
|
||||||
|
* @returns Updated connection string
|
||||||
|
*/
|
||||||
|
private updateConnectionStringForAccessToken(connString: string): string {
|
||||||
|
return connString ? connString.split(';').filter(prop =>
|
||||||
|
!['user', 'uid', 'password', 'pwd', 'authentication'].some(prefix => prop.toLocaleLowerCase().startsWith(prefix))
|
||||||
|
).join(';') : connString;
|
||||||
|
}
|
||||||
|
|
||||||
// private async getCountRowsInserted(): Promise<Number> {
|
// private async getCountRowsInserted(): Promise<Number> {
|
||||||
// let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId);
|
// let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId);
|
||||||
// let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(this.model.server.providerName, azdata.DataProviderType.QueryProvider);
|
// let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(this.model.server.providerName, azdata.DataProviderType.QueryProvider);
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
"Programming Languages"
|
"Programming Languages"
|
||||||
],
|
],
|
||||||
"enabledApiProposals": [
|
"enabledApiProposals": [
|
||||||
"documentPaste"
|
"documentPaste",
|
||||||
|
"notebookEditor"
|
||||||
],
|
],
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"onLanguage:markdown",
|
"onLanguage:markdown",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "4.7.0.29",
|
"version": "4.7.1.4",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-net7.0.zip",
|
"Windows_86": "win-x86-net7.0.zip",
|
||||||
"Windows_64": "win-x64-net7.0.zip",
|
"Windows_64": "win-x64-net7.0.zip",
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ export interface DeployParams {
|
|||||||
packageFilePath: string;
|
packageFilePath: string;
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
upgradeExisting: boolean;
|
upgradeExisting: boolean;
|
||||||
sqlCommandVariableValues?: Map<string, string>;
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
deploymentOptions?: mssql.DeploymentOptions;
|
deploymentOptions?: mssql.DeploymentOptions;
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
taskExecutionMode: TaskExecutionMode;
|
taskExecutionMode: TaskExecutionMode;
|
||||||
@@ -524,7 +524,7 @@ export interface DeployParams {
|
|||||||
export interface GenerateDeployScriptParams {
|
export interface GenerateDeployScriptParams {
|
||||||
packageFilePath: string;
|
packageFilePath: string;
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
sqlCommandVariableValues?: Map<string, string>;
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
deploymentOptions?: mssql.DeploymentOptions
|
deploymentOptions?: mssql.DeploymentOptions
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
taskExecutionMode: TaskExecutionMode;
|
taskExecutionMode: TaskExecutionMode;
|
||||||
@@ -555,7 +555,7 @@ export interface SavePublishProfileParams {
|
|||||||
profilePath: string;
|
profilePath: string;
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
connectionString: string;
|
connectionString: string;
|
||||||
sqlCommandVariableValues?: Map<string, string>;
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
deploymentOptions?: mssql.DeploymentOptions;
|
deploymentOptions?: mssql.DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ export class DacFxService extends BaseService implements mssql.IDacFxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async deployDacpac(packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<mssql.DacFxResult> {
|
public async deployDacpac(packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<mssql.DacFxResult> {
|
||||||
const params: contracts.DeployParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, upgradeExisting: upgradeExisting, sqlCommandVariableValues: sqlCommandVariableValues, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
const params: contracts.DeployParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, upgradeExisting: upgradeExisting, sqlCommandVariableValues: sqlCommandVariableValues ? Object.fromEntries(sqlCommandVariableValues) : undefined, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
return this.runWithErrorHandling(contracts.DeployRequest.type, params);
|
return this.runWithErrorHandling(contracts.DeployRequest.type, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async generateDeployScript(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<mssql.DacFxResult> {
|
public async generateDeployScript(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<mssql.DacFxResult> {
|
||||||
const params: contracts.GenerateDeployScriptParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, sqlCommandVariableValues: sqlCommandVariableValues, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
const params: contracts.GenerateDeployScriptParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, sqlCommandVariableValues: sqlCommandVariableValues ? Object.fromEntries(sqlCommandVariableValues) : undefined, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
return this.runWithErrorHandling(contracts.GenerateDeployScriptRequest.type, params);
|
return this.runWithErrorHandling(contracts.GenerateDeployScriptRequest.type, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ export class DacFxService extends BaseService implements mssql.IDacFxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<azdata.ResultStatus> {
|
public async savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<azdata.ResultStatus> {
|
||||||
const params: contracts.SavePublishProfileParams = { profilePath, databaseName, connectionString, sqlCommandVariableValues, deploymentOptions };
|
const params: contracts.SavePublishProfileParams = { profilePath, databaseName, connectionString, sqlCommandVariableValues: sqlCommandVariableValues ? Object.fromEntries(sqlCommandVariableValues) : undefined, deploymentOptions };
|
||||||
return this.runWithErrorHandling(contracts.SavePublishProfileRequest.type, params);
|
return this.runWithErrorHandling(contracts.SavePublishProfileRequest.type, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
111
extensions/mssql/src/mssql.d.ts
vendored
111
extensions/mssql/src/mssql.d.ts
vendored
@@ -917,7 +917,14 @@ declare module 'mssql' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface for the object view information
|
* Base interface for all the security principal objects. e.g. Login, Server Role, Database Role...
|
||||||
|
*/
|
||||||
|
export interface SecurityPrincipalObject extends SqlObject {
|
||||||
|
securablePermissions: SecurablePermissions[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base interface for the object view information.
|
||||||
*/
|
*/
|
||||||
export interface ObjectViewInfo<T extends SqlObject> {
|
export interface ObjectViewInfo<T extends SqlObject> {
|
||||||
/**
|
/**
|
||||||
@@ -926,10 +933,52 @@ declare module 'mssql' {
|
|||||||
objectInfo: T;
|
objectInfo: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Securable type metadata.
|
||||||
|
*/
|
||||||
|
export interface SecurableTypeMetadata {
|
||||||
|
/**
|
||||||
|
* Name of the securable type.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Display name of the securable type.
|
||||||
|
*/
|
||||||
|
displayName: string;
|
||||||
|
/**
|
||||||
|
* Permissions supported by the securable type.
|
||||||
|
*/
|
||||||
|
permissions: PermissionMetadata[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission metadata.
|
||||||
|
*/
|
||||||
|
export interface PermissionMetadata {
|
||||||
|
/**
|
||||||
|
* Name of the permission.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Display name of the permission.
|
||||||
|
*/
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base interface for security principal object's view information.
|
||||||
|
*/
|
||||||
|
export interface SecurityPrincipalViewInfo<T extends SecurityPrincipalObject> extends ObjectViewInfo<T> {
|
||||||
|
/**
|
||||||
|
* The securable types that the security principal object can be granted permissions on.
|
||||||
|
*/
|
||||||
|
supportedSecurableTypes: SecurableTypeMetadata[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server level login.
|
* Server level login.
|
||||||
*/
|
*/
|
||||||
export interface Login extends SqlObject {
|
export interface Login extends SecurityPrincipalObject {
|
||||||
/**
|
/**
|
||||||
* Authentication type.
|
* Authentication type.
|
||||||
*/
|
*/
|
||||||
@@ -1025,7 +1074,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* The information required to render the login view.
|
* The information required to render the login view.
|
||||||
*/
|
*/
|
||||||
export interface LoginViewInfo extends ObjectViewInfo<Login> {
|
export interface LoginViewInfo extends SecurityPrincipalViewInfo<Login> {
|
||||||
/**
|
/**
|
||||||
* The authentication types supported by the server.
|
* The authentication types supported by the server.
|
||||||
*/
|
*/
|
||||||
@@ -1062,20 +1111,24 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* The permission information a principal has on a securable.
|
* The permission information a principal has on a securable.
|
||||||
*/
|
*/
|
||||||
export interface Permission {
|
export interface SecurablePermissionItem {
|
||||||
/**
|
/**
|
||||||
* Name of the permission.
|
* name of the permission.
|
||||||
*/
|
*/
|
||||||
name: string;
|
permission: string;
|
||||||
/**
|
/**
|
||||||
* Whether the permission is granted or denied.
|
* Name of the grantor.
|
||||||
*/
|
*/
|
||||||
grant: boolean;
|
grantor: string;
|
||||||
|
/**
|
||||||
|
* Whether the permission is granted or denied. Undefined means not specified.
|
||||||
|
*/
|
||||||
|
grant?: boolean;
|
||||||
/**
|
/**
|
||||||
* Whether the pincipal can grant this permission to other principals.
|
* Whether the pincipal can grant this permission to other principals.
|
||||||
* The value will be ignored if the grant property is set to false.
|
* The value will be ignored if the grant property is set to false.
|
||||||
*/
|
*/
|
||||||
withGrant: boolean;
|
withGrant?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1083,13 +1136,25 @@ declare module 'mssql' {
|
|||||||
*/
|
*/
|
||||||
export interface SecurablePermissions {
|
export interface SecurablePermissions {
|
||||||
/**
|
/**
|
||||||
* The securable.
|
* The securable name.
|
||||||
*/
|
*/
|
||||||
securable: SqlObject;
|
name: string;
|
||||||
/**
|
/**
|
||||||
* The Permissions.
|
* The securable type.
|
||||||
*/
|
*/
|
||||||
permissions: Permission[];
|
type: string;
|
||||||
|
/**
|
||||||
|
* The schema name of the object if applicable.
|
||||||
|
*/
|
||||||
|
schema?: string;
|
||||||
|
/**
|
||||||
|
* The permissions.
|
||||||
|
*/
|
||||||
|
permissions: SecurablePermissionItem[];
|
||||||
|
/**
|
||||||
|
* The effective permissions. Includes all permissions granted to the principal, including those granted through role memberships.
|
||||||
|
*/
|
||||||
|
effectivePermissions: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1135,7 +1200,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Database user.
|
* Database user.
|
||||||
*/
|
*/
|
||||||
export interface User extends SqlObject {
|
export interface User extends SecurityPrincipalObject {
|
||||||
/**
|
/**
|
||||||
* Type of the user.
|
* Type of the user.
|
||||||
*/
|
*/
|
||||||
@@ -1172,7 +1237,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* The information required to render the user view.
|
* The information required to render the user view.
|
||||||
*/
|
*/
|
||||||
export interface UserViewInfo extends ObjectViewInfo<User> {
|
export interface UserViewInfo extends SecurityPrincipalViewInfo<User> {
|
||||||
/**
|
/**
|
||||||
* All user types supported by the database.
|
* All user types supported by the database.
|
||||||
*/
|
*/
|
||||||
@@ -1198,7 +1263,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Interface representing the server role object.
|
* Interface representing the server role object.
|
||||||
*/
|
*/
|
||||||
export interface ServerRoleInfo extends SqlObject {
|
export interface ServerRoleInfo extends SecurityPrincipalObject {
|
||||||
/**
|
/**
|
||||||
* Name of the server principal that owns the server role.
|
* Name of the server principal that owns the server role.
|
||||||
*/
|
*/
|
||||||
@@ -1216,7 +1281,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Interface representing the information required to render the server role view.
|
* Interface representing the information required to render the server role view.
|
||||||
*/
|
*/
|
||||||
export interface ServerRoleViewInfo extends ObjectViewInfo<ServerRoleInfo> {
|
export interface ServerRoleViewInfo extends SecurityPrincipalViewInfo<ServerRoleInfo> {
|
||||||
/**
|
/**
|
||||||
* Whether the server role is a fixed role.
|
* Whether the server role is a fixed role.
|
||||||
*/
|
*/
|
||||||
@@ -1230,7 +1295,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Interface representing the application role object.
|
* Interface representing the application role object.
|
||||||
*/
|
*/
|
||||||
export interface ApplicationRoleInfo extends SqlObject {
|
export interface ApplicationRoleInfo extends SecurityPrincipalObject {
|
||||||
/**
|
/**
|
||||||
* Default schema of the application role.
|
* Default schema of the application role.
|
||||||
*/
|
*/
|
||||||
@@ -1248,7 +1313,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Interface representing the information required to render the application role view.
|
* Interface representing the information required to render the application role view.
|
||||||
*/
|
*/
|
||||||
export interface ApplicationRoleViewInfo extends ObjectViewInfo<ApplicationRoleInfo> {
|
export interface ApplicationRoleViewInfo extends SecurityPrincipalViewInfo<ApplicationRoleInfo> {
|
||||||
/**
|
/**
|
||||||
* List of all the schemas in the database.
|
* List of all the schemas in the database.
|
||||||
*/
|
*/
|
||||||
@@ -1258,7 +1323,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Interface representing the database role object.
|
* Interface representing the database role object.
|
||||||
*/
|
*/
|
||||||
export interface DatabaseRoleInfo extends SqlObject {
|
export interface DatabaseRoleInfo extends SecurityPrincipalObject {
|
||||||
/**
|
/**
|
||||||
* Name of the database principal that owns the database role.
|
* Name of the database principal that owns the database role.
|
||||||
*/
|
*/
|
||||||
@@ -1276,7 +1341,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* Interface representing the information required to render the database role view.
|
* Interface representing the information required to render the database role view.
|
||||||
*/
|
*/
|
||||||
export interface DatabaseRoleViewInfo extends ObjectViewInfo<DatabaseRoleInfo> {
|
export interface DatabaseRoleViewInfo extends SecurityPrincipalViewInfo<DatabaseRoleInfo> {
|
||||||
/**
|
/**
|
||||||
* List of all the schemas in the database.
|
* List of all the schemas in the database.
|
||||||
*/
|
*/
|
||||||
@@ -1294,7 +1359,7 @@ declare module 'mssql' {
|
|||||||
/**
|
/**
|
||||||
* type of the object.
|
* type of the object.
|
||||||
*/
|
*/
|
||||||
type: NodeType;
|
type: string;
|
||||||
/**
|
/**
|
||||||
* schema of the object.
|
* schema of the object.
|
||||||
*/
|
*/
|
||||||
@@ -1369,7 +1434,7 @@ declare module 'mssql' {
|
|||||||
* @param searchText Search text.
|
* @param searchText Search text.
|
||||||
* @param schema Schema to search in.
|
* @param schema Schema to search in.
|
||||||
*/
|
*/
|
||||||
search(contextId: string, objectTypes: ObjectManagement.NodeType[], searchText?: string, schema?: string): Thenable<ObjectManagement.SearchResultItem[]>;
|
search(contextId: string, objectTypes: string[], searchText?: string, schema?: string): Thenable<ObjectManagement.SearchResultItem[]>;
|
||||||
}
|
}
|
||||||
// Object Management - End.
|
// Object Management - End.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,22 @@ export const RenameObjectDialogTitle: string = localize('objectManagement.rename
|
|||||||
export const OwnerText: string = localize('objectManagement.ownerText', "Owner");
|
export const OwnerText: string = localize('objectManagement.ownerText', "Owner");
|
||||||
export const BrowseText = localize('objectManagement.browseText', "Browse…");
|
export const BrowseText = localize('objectManagement.browseText', "Browse…");
|
||||||
export const BrowseOwnerButtonAriaLabel = localize('objectManagement.browseForOwnerText', "Browse for an owner");
|
export const BrowseOwnerButtonAriaLabel = localize('objectManagement.browseForOwnerText', "Browse for an owner");
|
||||||
export const AddMemberAriaLabel = localize('objectManagement.addMemberText', "Add a member");
|
export const AddMemberAriaLabel = localize('objectManagement.addMembersText', "Add members");
|
||||||
export const RemoveMemberAriaLabel = localize('objectManagement.removeMemberText', "Remove selected member");
|
export const RemoveMemberAriaLabel = localize('objectManagement.removeMemberText', "Remove selected member");
|
||||||
|
export const AddSecurableAriaLabel = localize('objectManagement.addSecurablesText', "Add securables");
|
||||||
|
export const RemoveSecurableAriaLabel = localize('objectManagement.removeSecurablesText', "Remove selected securable");
|
||||||
|
export const SecurablesText = localize('objectManagement.securablesText', "Securables");
|
||||||
|
export const ExplicitPermissionsTableLabel = localize('objectManagement.explicitPermissionsTableLabel', "Explicit permissions for selected securable");
|
||||||
|
export const EffectivePermissionsTableLabel = localize('objectManagement.effectivePermissionsTableLabel', "Effective permissions for selected securable");
|
||||||
|
export const PermissionColumnHeader = localize('objectManagement.permissionColumnHeader', "Permission");
|
||||||
|
export const GrantorColumnHeader = localize('objectManagement.grantorColumnHeader', "Grantor");
|
||||||
|
export const GrantColumnHeader = localize('objectManagement.grantColumnHeader', "Grant");
|
||||||
|
export const WithGrantColumnHeader = localize('objectManagement.withGrantColumnHeader', "With Grant");
|
||||||
|
export const DenyColumnHeader = localize('objectManagement.denyColumnHeader', "Deny");
|
||||||
|
export const SelectSecurablesDialogTitle = localize('objectManagement.selectSecurablesDialogTitle', "Select Securables");
|
||||||
|
|
||||||
|
export function ExplicitPermissionsTableLabelSelected(name: string): string { return localize('objectManagement.explicitPermissionsTableLabelSelected', "Explicit permissions for: {0}", name); }
|
||||||
|
export function EffectivePermissionsTableLabelSelected(name: string): string { return localize('objectManagement.effectivePermissionsTableLabelSelected', "Effective permissions for: {0}", name); }
|
||||||
|
|
||||||
export function RefreshObjectExplorerError(error: string): string {
|
export function RefreshObjectExplorerError(error: string): string {
|
||||||
return localize({
|
return localize({
|
||||||
@@ -133,12 +146,15 @@ export const LoginNotSelectedError = localize('objectManagement.loginNotSelected
|
|||||||
export const MembershipSectionHeader = localize('objectManagement.membershipLabel', "Membership");
|
export const MembershipSectionHeader = localize('objectManagement.membershipLabel', "Membership");
|
||||||
export const MemberSectionHeader = localize('objectManagement.membersLabel', "Members");
|
export const MemberSectionHeader = localize('objectManagement.membersLabel', "Members");
|
||||||
export const SchemaText = localize('objectManagement.schemaLabel', "Schema");
|
export const SchemaText = localize('objectManagement.schemaLabel', "Schema");
|
||||||
|
|
||||||
|
// Database
|
||||||
export const DatabaseExistsError = (dbName: string) => localize('objectManagement.databaseExistsError', "Database '{0}' already exists. Choose a different database name.", dbName);
|
export const DatabaseExistsError = (dbName: string) => localize('objectManagement.databaseExistsError', "Database '{0}' already exists. Choose a different database name.", dbName);
|
||||||
export const CollationText = localize('objectManagement.collationLabel', "Collation");
|
export const CollationText = localize('objectManagement.collationLabel', "Collation");
|
||||||
export const RecoveryModelText = localize('objectManagement.recoveryModelLabel', "Recovery Model");
|
export const RecoveryModelText = localize('objectManagement.recoveryModelLabel', "Recovery Model");
|
||||||
export const CompatibilityLevelText = localize('objectManagement.compatibilityLevelLabel', "Compatibility Level");
|
export const CompatibilityLevelText = localize('objectManagement.compatibilityLevelLabel', "Compatibility Level");
|
||||||
export const ContainmentTypeText = localize('objectManagement.containmentTypeLabel', "Containment Type");
|
export const ContainmentTypeText = localize('objectManagement.containmentTypeLabel', "Containment Type");
|
||||||
|
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
export const BlankPasswordConfirmationText: string = localize('objectManagement.blankPasswordConfirmation', "Creating a login with a blank password is a security risk. Are you sure you want to continue?");
|
export const BlankPasswordConfirmationText: string = localize('objectManagement.blankPasswordConfirmation', "Creating a login with a blank password is a security risk. Are you sure you want to continue?");
|
||||||
export const DeleteLoginConfirmationText: string = localize('objectManagement.deleteLoginConfirmation', "Deleting server logins does not delete the database users associated with the logins. To complete the process, delete the users in each database. It may be necessary to first transfer the ownership of schemas to new users.");
|
export const DeleteLoginConfirmationText: string = localize('objectManagement.deleteLoginConfirmation', "Deleting server logins does not delete the database users associated with the logins. To complete the process, delete the users in each database. It may be necessary to first transfer the ownership of schemas to new users.");
|
||||||
|
|||||||
@@ -67,6 +67,126 @@ export class ObjectManagementService extends BaseService implements IObjectManag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ServerLevelSecurableTypes: ObjectManagement.SecurableTypeMetadata[] = [
|
||||||
|
{
|
||||||
|
name: 'Server',
|
||||||
|
displayName: 'Server',
|
||||||
|
permissions: [{
|
||||||
|
name: 'CONNECT SQL',
|
||||||
|
displayName: 'CONNECT SQL'
|
||||||
|
}, {
|
||||||
|
name: 'VIEW ANY DATABASE',
|
||||||
|
displayName: 'VIEW ANY DATABASE'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
name: 'ServerRole',
|
||||||
|
displayName: 'Server Role',
|
||||||
|
permissions: [{
|
||||||
|
name: 'ALTER',
|
||||||
|
displayName: 'ALTER'
|
||||||
|
}, {
|
||||||
|
name: 'CONTROL',
|
||||||
|
displayName: 'CONTROL'
|
||||||
|
}, {
|
||||||
|
name: 'TAKE OWNERSHIP',
|
||||||
|
displayName: 'TAKE OWNERSHIP'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const DatabaseLevelSecurableTypes: ObjectManagement.SecurableTypeMetadata[] = [
|
||||||
|
{
|
||||||
|
name: 'AggregateFunction',
|
||||||
|
displayName: 'Aggregate Function',
|
||||||
|
permissions: [{
|
||||||
|
name: 'EXECUTE',
|
||||||
|
displayName: 'EXECUTE'
|
||||||
|
}, {
|
||||||
|
name: 'ALTER',
|
||||||
|
displayName: 'ALTER'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
name: 'Table',
|
||||||
|
displayName: 'Table',
|
||||||
|
permissions: [{
|
||||||
|
name: 'SELECT',
|
||||||
|
displayName: 'SELECT'
|
||||||
|
}, {
|
||||||
|
name: 'ALTER',
|
||||||
|
displayName: 'ALTER'
|
||||||
|
}, {
|
||||||
|
name: 'CONTROL',
|
||||||
|
displayName: 'CONTROL'
|
||||||
|
}, {
|
||||||
|
name: 'TAKE OWNERSHIP',
|
||||||
|
displayName: 'TAKE OWNERSHIP'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
name: 'View',
|
||||||
|
displayName: 'View',
|
||||||
|
permissions: [{
|
||||||
|
name: 'ALTER',
|
||||||
|
displayName: 'ALTER'
|
||||||
|
}, {
|
||||||
|
name: 'CONTROL',
|
||||||
|
displayName: 'CONTROL'
|
||||||
|
}, {
|
||||||
|
name: 'TAKE OWNERSHIP',
|
||||||
|
displayName: 'TAKE OWNERSHIP'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const ServerLevelPermissions: ObjectManagement.SecurablePermissions[] = [
|
||||||
|
{
|
||||||
|
name: 'Server',
|
||||||
|
type: 'Server',
|
||||||
|
permissions: [
|
||||||
|
{
|
||||||
|
permission: 'CONNECT SQL',
|
||||||
|
grant: true,
|
||||||
|
grantor: 'sa',
|
||||||
|
withGrant: undefined
|
||||||
|
}, {
|
||||||
|
permission: 'VIEW ANY DATABASE',
|
||||||
|
grant: false,
|
||||||
|
grantor: 'sa',
|
||||||
|
withGrant: undefined
|
||||||
|
}
|
||||||
|
],
|
||||||
|
effectivePermissions: ['CONNECT SQL', 'VIEW ANY DATABASE']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const DatabaseLevelPermissions: ObjectManagement.SecurablePermissions[] = [
|
||||||
|
{
|
||||||
|
name: 'table1',
|
||||||
|
type: 'Table',
|
||||||
|
schema: 'dbo',
|
||||||
|
permissions: [
|
||||||
|
{
|
||||||
|
permission: 'SELECT',
|
||||||
|
grant: true,
|
||||||
|
grantor: '',
|
||||||
|
withGrant: undefined
|
||||||
|
}
|
||||||
|
],
|
||||||
|
effectivePermissions: ['SELECT']
|
||||||
|
}, {
|
||||||
|
name: 'view1',
|
||||||
|
type: 'View',
|
||||||
|
schema: 'Sales',
|
||||||
|
permissions: [
|
||||||
|
{
|
||||||
|
permission: 'ALTER',
|
||||||
|
grant: true,
|
||||||
|
grantor: '',
|
||||||
|
withGrant: undefined
|
||||||
|
}
|
||||||
|
],
|
||||||
|
effectivePermissions: ['ALTER']
|
||||||
|
}
|
||||||
|
];
|
||||||
export class TestObjectManagementService implements IObjectManagementService {
|
export class TestObjectManagementService implements IObjectManagementService {
|
||||||
initializeView(contextId: string, objectType: ObjectManagement.NodeType, connectionUri: string, database: string, isNewObject: boolean, parentUrn: string, objectUrn: string): Thenable<ObjectManagement.ObjectViewInfo<ObjectManagement.SqlObject>> {
|
initializeView(contextId: string, objectType: ObjectManagement.NodeType, connectionUri: string, database: string, isNewObject: boolean, parentUrn: string, objectUrn: string): Thenable<ObjectManagement.ObjectViewInfo<ObjectManagement.SqlObject>> {
|
||||||
let obj;
|
let obj;
|
||||||
@@ -102,18 +222,18 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
return this.delayAndResolve();
|
return this.delayAndResolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(contextId: string, objectTypes: ObjectManagement.NodeType[], searchText: string, schema: string): Promise<ObjectManagement.SearchResultItem[]> {
|
async search(contextId: string, objectTypes: ObjectManagement.NodeType[], searchText?: string, schema?: string): Promise<ObjectManagement.SearchResultItem[]> {
|
||||||
const items: ObjectManagement.SearchResultItem[] = [];
|
const items: ObjectManagement.SearchResultItem[] = [];
|
||||||
objectTypes.forEach(type => {
|
objectTypes.forEach(type => {
|
||||||
items.push(...this.generateSearchResult(type, 15));
|
items.push(...this.generateSearchResult(type, schema, 15));
|
||||||
});
|
});
|
||||||
return this.delayAndResolve(items);
|
return this.delayAndResolve(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateSearchResult(objectType: ObjectManagement.NodeType, count: number): ObjectManagement.SearchResultItem[] {
|
private generateSearchResult(objectType: ObjectManagement.NodeType, schema: string | undefined, count: number): ObjectManagement.SearchResultItem[] {
|
||||||
let items: ObjectManagement.SearchResultItem[] = [];
|
let items: ObjectManagement.SearchResultItem[] = [];
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
items.push(<ObjectManagement.SearchResultItem>{ name: `${objectType} ${i}`, type: objectType });
|
items.push(<ObjectManagement.SearchResultItem>{ name: `${objectType} ${i}`, schema: schema, type: objectType });
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
@@ -136,7 +256,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
serverRoles: ['public', 'bulkadmin'],
|
serverRoles: ['public', 'bulkadmin'],
|
||||||
connectPermission: true,
|
connectPermission: true,
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
isLockedOut: false
|
isLockedOut: false,
|
||||||
|
securablePermissions: []
|
||||||
},
|
},
|
||||||
authenticationTypes: [ObjectManagement.AuthenticationType.Sql, ObjectManagement.AuthenticationType.Windows],
|
authenticationTypes: [ObjectManagement.AuthenticationType.Sql, ObjectManagement.AuthenticationType.Windows],
|
||||||
supportAdvancedOptions: true,
|
supportAdvancedOptions: true,
|
||||||
@@ -144,7 +265,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
canEditLockedOutState: false,
|
canEditLockedOutState: false,
|
||||||
languages: languages,
|
languages: languages,
|
||||||
databases: databases,
|
databases: databases,
|
||||||
serverRoles: serverRoles
|
serverRoles: serverRoles,
|
||||||
|
supportedSecurableTypes: ServerLevelSecurableTypes
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
login = <ObjectManagement.LoginViewInfo>{
|
login = <ObjectManagement.LoginViewInfo>{
|
||||||
@@ -160,7 +282,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
connectPermission: true,
|
connectPermission: true,
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
isLockedOut: false,
|
isLockedOut: false,
|
||||||
password: '******************'
|
password: '******************',
|
||||||
|
securablePermissions: ServerLevelPermissions
|
||||||
},
|
},
|
||||||
authenticationTypes: [ObjectManagement.AuthenticationType.Sql, ObjectManagement.AuthenticationType.Windows],
|
authenticationTypes: [ObjectManagement.AuthenticationType.Sql, ObjectManagement.AuthenticationType.Windows],
|
||||||
supportAdvancedOptions: true,
|
supportAdvancedOptions: true,
|
||||||
@@ -168,7 +291,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
canEditLockedOutState: false,
|
canEditLockedOutState: false,
|
||||||
languages: languages,
|
languages: languages,
|
||||||
databases: databases,
|
databases: databases,
|
||||||
serverRoles: serverRoles
|
serverRoles: serverRoles,
|
||||||
|
supportedSecurableTypes: ServerLevelSecurableTypes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return login;
|
return login;
|
||||||
@@ -192,7 +316,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
loginName: 'sa',
|
loginName: 'sa',
|
||||||
ownedSchemas: [],
|
ownedSchemas: [],
|
||||||
databaseRoles: [],
|
databaseRoles: [],
|
||||||
password: ''
|
password: '',
|
||||||
|
securablePermissions: []
|
||||||
},
|
},
|
||||||
languages: languages,
|
languages: languages,
|
||||||
schemas: schemas,
|
schemas: schemas,
|
||||||
@@ -203,7 +328,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
ObjectManagement.UserType.AADAuthentication,
|
ObjectManagement.UserType.AADAuthentication,
|
||||||
ObjectManagement.UserType.SqlAuthentication,
|
ObjectManagement.UserType.SqlAuthentication,
|
||||||
ObjectManagement.UserType.NoLoginAccess
|
ObjectManagement.UserType.NoLoginAccess
|
||||||
]
|
],
|
||||||
|
supportedSecurableTypes: DatabaseLevelSecurableTypes
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
viewInfo = {
|
viewInfo = {
|
||||||
@@ -214,7 +340,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
defaultLanguage: '<default>',
|
defaultLanguage: '<default>',
|
||||||
loginName: 'sa',
|
loginName: 'sa',
|
||||||
ownedSchemas: ['dbo'],
|
ownedSchemas: ['dbo'],
|
||||||
databaseRoles: ['dbmanager', 'bulkadmin']
|
databaseRoles: ['dbmanager', 'bulkadmin'],
|
||||||
|
securablePermissions: DatabaseLevelPermissions
|
||||||
},
|
},
|
||||||
languages: languages,
|
languages: languages,
|
||||||
schemas: schemas,
|
schemas: schemas,
|
||||||
@@ -225,7 +352,8 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
ObjectManagement.UserType.AADAuthentication,
|
ObjectManagement.UserType.AADAuthentication,
|
||||||
ObjectManagement.UserType.SqlAuthentication,
|
ObjectManagement.UserType.SqlAuthentication,
|
||||||
ObjectManagement.UserType.NoLoginAccess
|
ObjectManagement.UserType.NoLoginAccess
|
||||||
]
|
],
|
||||||
|
supportedSecurableTypes: DatabaseLevelSecurableTypes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return viewInfo;
|
return viewInfo;
|
||||||
@@ -237,19 +365,23 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
name: '',
|
name: '',
|
||||||
members: [],
|
members: [],
|
||||||
owner: '',
|
owner: '',
|
||||||
memberships: []
|
memberships: [],
|
||||||
|
securablePermissions: []
|
||||||
},
|
},
|
||||||
isFixedRole: false,
|
isFixedRole: false,
|
||||||
serverRoles: ['ServerLevelServerRole 1', 'ServerLevelServerRole 2', 'ServerLevelServerRole 3', 'ServerLevelServerRole 4'],
|
serverRoles: ['ServerLevelServerRole 1', 'ServerLevelServerRole 2', 'ServerLevelServerRole 3', 'ServerLevelServerRole 4'],
|
||||||
|
supportedSecurableTypes: ServerLevelSecurableTypes
|
||||||
} : <ObjectManagement.ServerRoleViewInfo>{
|
} : <ObjectManagement.ServerRoleViewInfo>{
|
||||||
objectInfo: {
|
objectInfo: {
|
||||||
name: 'ServerLevelServerRole 1',
|
name: 'ServerLevelServerRole 1',
|
||||||
members: ['ServerLevelLogin 1', 'ServerLevelServerRole 2'],
|
members: ['ServerLevelLogin 1', 'ServerLevelServerRole 2'],
|
||||||
owner: 'ServerLevelLogin 2',
|
owner: 'ServerLevelLogin 2',
|
||||||
memberships: ['ServerLevelServerRole 3', 'ServerLevelServerRole 4']
|
memberships: ['ServerLevelServerRole 3', 'ServerLevelServerRole 4'],
|
||||||
|
securablePermissions: ServerLevelPermissions
|
||||||
},
|
},
|
||||||
isFixedRole: false,
|
isFixedRole: false,
|
||||||
serverRoles: ['ServerLevelServerRole 2', 'ServerLevelServerRole 3', 'ServerLevelServerRole 4']
|
serverRoles: ['ServerLevelServerRole 2', 'ServerLevelServerRole 3', 'ServerLevelServerRole 4'],
|
||||||
|
supportedSecurableTypes: ServerLevelSecurableTypes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,16 +391,20 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
name: '',
|
name: '',
|
||||||
defaultSchema: 'dbo',
|
defaultSchema: 'dbo',
|
||||||
ownedSchemas: [],
|
ownedSchemas: [],
|
||||||
|
securablePermissions: []
|
||||||
},
|
},
|
||||||
schemas: ['dbo', 'sys', 'admin']
|
schemas: ['dbo', 'sys', 'admin'],
|
||||||
|
supportedSecurableTypes: []
|
||||||
} : <ObjectManagement.ApplicationRoleViewInfo>{
|
} : <ObjectManagement.ApplicationRoleViewInfo>{
|
||||||
objectInfo: {
|
objectInfo: {
|
||||||
name: 'app role1',
|
name: 'app role1',
|
||||||
password: '******************',
|
password: '******************',
|
||||||
defaultSchema: 'dbo',
|
defaultSchema: 'dbo',
|
||||||
ownedSchemas: ['dbo'],
|
ownedSchemas: ['dbo'],
|
||||||
|
securablePermissions: DatabaseLevelPermissions
|
||||||
},
|
},
|
||||||
schemas: ['dbo', 'sys', 'admin']
|
schemas: ['dbo', 'sys', 'admin'],
|
||||||
|
supportedSecurableTypes: DatabaseLevelSecurableTypes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,17 +414,21 @@ export class TestObjectManagementService implements IObjectManagementService {
|
|||||||
name: '',
|
name: '',
|
||||||
owner: '',
|
owner: '',
|
||||||
members: [],
|
members: [],
|
||||||
ownedSchemas: []
|
ownedSchemas: [],
|
||||||
|
securablePermissions: []
|
||||||
},
|
},
|
||||||
schemas: ['dbo', 'sys', 'admin']
|
schemas: ['dbo', 'sys', 'admin'],
|
||||||
|
supportedSecurableTypes: DatabaseLevelSecurableTypes
|
||||||
} : <ObjectManagement.DatabaseRoleViewInfo>{
|
} : <ObjectManagement.DatabaseRoleViewInfo>{
|
||||||
objectInfo: {
|
objectInfo: {
|
||||||
name: 'db role1',
|
name: 'db role1',
|
||||||
owner: '',
|
owner: '',
|
||||||
members: [],
|
members: [],
|
||||||
ownedSchemas: ['dbo']
|
ownedSchemas: ['dbo'],
|
||||||
|
securablePermissions: DatabaseLevelPermissions
|
||||||
},
|
},
|
||||||
schemas: ['dbo', 'sys', 'admin']
|
schemas: ['dbo', 'sys', 'admin'],
|
||||||
|
supportedSecurableTypes: DatabaseLevelSecurableTypes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { AlterApplicationRoleDocUrl, CreateApplicationRoleDocUrl } from '../constants';
|
import { AlterApplicationRoleDocUrl, CreateApplicationRoleDocUrl } from '../constants';
|
||||||
import { isValidSQLPassword } from '../utils';
|
import { isValidSQLPassword } from '../utils';
|
||||||
import { DefaultMaxTableHeight } from '../../ui/dialogBase';
|
import { DefaultMaxTableRowCount } from '../../ui/dialogBase';
|
||||||
|
import { PrincipalDialogBase } from './principalDialogBase';
|
||||||
|
|
||||||
export class ApplicationRoleDialog extends ObjectManagementDialogBase<ObjectManagement.ApplicationRoleInfo, ObjectManagement.ApplicationRoleViewInfo> {
|
export class ApplicationRoleDialog extends PrincipalDialogBase<ObjectManagement.ApplicationRoleInfo, ObjectManagement.ApplicationRoleViewInfo> {
|
||||||
// Sections
|
// Sections
|
||||||
private generalSection: azdata.GroupContainer;
|
private generalSection: azdata.GroupContainer;
|
||||||
private ownedSchemasSection: azdata.GroupContainer;
|
private ownedSchemasSection: azdata.GroupContainer;
|
||||||
@@ -25,7 +26,7 @@ export class ApplicationRoleDialog extends ObjectManagementDialogBase<ObjectMana
|
|||||||
private ownedSchemaTable: azdata.TableComponent;
|
private ownedSchemaTable: azdata.TableComponent;
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
super(objectManagementService, options);
|
super(objectManagementService, options, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override postInitializeData(): void {
|
protected override postInitializeData(): void {
|
||||||
@@ -51,10 +52,11 @@ export class ApplicationRoleDialog extends ObjectManagementDialogBase<ObjectMana
|
|||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeUI(): Promise<void> {
|
protected override async initializeUI(): Promise<void> {
|
||||||
|
await super.initializeUI();
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
this.initializeOwnedSchemasSection();
|
this.initializeOwnedSchemasSection();
|
||||||
this.formContainer.addItems([this.generalSection, this.ownedSchemasSection]);
|
this.formContainer.addItems([this.generalSection, this.ownedSchemasSection, this.securableSection], this.getSectionItemLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeGeneralSection(): void {
|
private initializeGeneralSection(): void {
|
||||||
@@ -84,7 +86,7 @@ export class ApplicationRoleDialog extends ObjectManagementDialogBase<ObjectMana
|
|||||||
[localizedConstants.SchemaText],
|
[localizedConstants.SchemaText],
|
||||||
this.viewInfo.schemas,
|
this.viewInfo.schemas,
|
||||||
this.objectInfo.ownedSchemas,
|
this.objectInfo.ownedSchemas,
|
||||||
DefaultMaxTableHeight,
|
DefaultMaxTableRowCount,
|
||||||
(item) => {
|
(item) => {
|
||||||
// It is not allowed to have unassigned schema.
|
// It is not allowed to have unassigned schema.
|
||||||
return this.objectInfo.ownedSchemas.indexOf(item) === -1;
|
return this.objectInfo.ownedSchemas.indexOf(item) === -1;
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { AlterDatabaseRoleDocUrl, CreateDatabaseRoleDocUrl } from '../constants';
|
import { AlterDatabaseRoleDocUrl, CreateDatabaseRoleDocUrl } from '../constants';
|
||||||
import { FindObjectDialog } from './findObjectDialog';
|
import { FindObjectDialog } from './findObjectDialog';
|
||||||
import { DefaultMaxTableHeight } from '../../ui/dialogBase';
|
import { DefaultMaxTableRowCount } from '../../ui/dialogBase';
|
||||||
|
import { PrincipalDialogBase } from './principalDialogBase';
|
||||||
|
|
||||||
export class DatabaseRoleDialog extends ObjectManagementDialogBase<ObjectManagement.DatabaseRoleInfo, ObjectManagement.DatabaseRoleViewInfo> {
|
export class DatabaseRoleDialog extends PrincipalDialogBase<ObjectManagement.DatabaseRoleInfo, ObjectManagement.DatabaseRoleViewInfo> {
|
||||||
// Sections
|
// Sections
|
||||||
private generalSection: azdata.GroupContainer;
|
private generalSection: azdata.GroupContainer;
|
||||||
private ownedSchemasSection: azdata.GroupContainer;
|
private ownedSchemasSection: azdata.GroupContainer;
|
||||||
@@ -27,18 +28,19 @@ export class DatabaseRoleDialog extends ObjectManagementDialogBase<ObjectManagem
|
|||||||
private memberTable: azdata.TableComponent;
|
private memberTable: azdata.TableComponent;
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
super(objectManagementService, options);
|
super(objectManagementService, options, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override get helpUrl(): string {
|
protected override get helpUrl(): string {
|
||||||
return this.options.isNewObject ? CreateDatabaseRoleDocUrl : AlterDatabaseRoleDocUrl;
|
return this.options.isNewObject ? CreateDatabaseRoleDocUrl : AlterDatabaseRoleDocUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeUI(): Promise<void> {
|
protected override async initializeUI(): Promise<void> {
|
||||||
|
await super.initializeUI();
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
this.initializeOwnedSchemasSection();
|
this.initializeOwnedSchemasSection();
|
||||||
this.initializeMemberSection();
|
this.initializeMemberSection();
|
||||||
this.formContainer.addItems([this.generalSection, this.ownedSchemasSection, this.memberSection]);
|
this.formContainer.addItems([this.generalSection, this.ownedSchemasSection, this.memberSection, this.securableSection], this.getSectionItemLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeGeneralSection(): void {
|
private initializeGeneralSection(): void {
|
||||||
@@ -53,9 +55,11 @@ export class DatabaseRoleDialog extends ObjectManagementDialogBase<ObjectManagem
|
|||||||
const browseOwnerButton = this.createButton(localizedConstants.BrowseText, localizedConstants.BrowseOwnerButtonAriaLabel, async () => {
|
const browseOwnerButton = this.createButton(localizedConstants.BrowseText, localizedConstants.BrowseOwnerButtonAriaLabel, async () => {
|
||||||
const dialog = new FindObjectDialog(this.objectManagementService, {
|
const dialog = new FindObjectDialog(this.objectManagementService, {
|
||||||
objectTypes: [ObjectManagement.NodeType.ApplicationRole, ObjectManagement.NodeType.DatabaseRole, ObjectManagement.NodeType.User],
|
objectTypes: [ObjectManagement.NodeType.ApplicationRole, ObjectManagement.NodeType.DatabaseRole, ObjectManagement.NodeType.User],
|
||||||
|
selectAllObjectTypes: true,
|
||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
contextId: this.contextId,
|
contextId: this.contextId,
|
||||||
title: localizedConstants.SelectDatabaseRoleOwnerDialogTitle
|
title: localizedConstants.SelectDatabaseRoleOwnerDialogTitle,
|
||||||
|
showSchemaColumn: false
|
||||||
});
|
});
|
||||||
await dialog.open();
|
await dialog.open();
|
||||||
const result = await dialog.waitForClose();
|
const result = await dialog.waitForClose();
|
||||||
@@ -70,48 +74,45 @@ export class DatabaseRoleDialog extends ObjectManagementDialogBase<ObjectManagem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeMemberSection(): void {
|
private initializeMemberSection(): void {
|
||||||
this.memberTable = this.createTable(localizedConstants.MemberSectionHeader, [
|
this.memberTable = this.createTable(localizedConstants.MemberSectionHeader, [localizedConstants.NameText], this.objectInfo.members.map(m => [m]));
|
||||||
{
|
|
||||||
type: azdata.ColumnType.text,
|
|
||||||
value: localizedConstants.NameText
|
|
||||||
}
|
|
||||||
], this.objectInfo.members.map(m => [m]));
|
|
||||||
const buttonContainer = this.addButtonsForTable(this.memberTable, localizedConstants.AddMemberAriaLabel, localizedConstants.RemoveMemberAriaLabel,
|
const buttonContainer = this.addButtonsForTable(this.memberTable, localizedConstants.AddMemberAriaLabel, localizedConstants.RemoveMemberAriaLabel,
|
||||||
async () => {
|
async () => {
|
||||||
const dialog = new FindObjectDialog(this.objectManagementService, {
|
const dialog = new FindObjectDialog(this.objectManagementService, {
|
||||||
objectTypes: [ObjectManagement.NodeType.DatabaseRole, ObjectManagement.NodeType.User],
|
objectTypes: [ObjectManagement.NodeType.DatabaseRole, ObjectManagement.NodeType.User],
|
||||||
|
selectAllObjectTypes: true,
|
||||||
multiSelect: true,
|
multiSelect: true,
|
||||||
contextId: this.contextId,
|
contextId: this.contextId,
|
||||||
title: localizedConstants.SelectDatabaseRoleMemberDialogTitle
|
title: localizedConstants.SelectDatabaseRoleMemberDialogTitle,
|
||||||
|
showSchemaColumn: false
|
||||||
});
|
});
|
||||||
await dialog.open();
|
await dialog.open();
|
||||||
const result = await dialog.waitForClose();
|
const result = await dialog.waitForClose();
|
||||||
this.addMembers(result.selectedObjects.map(r => r.name));
|
await this.addMembers(result.selectedObjects.map(r => r.name));
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
if (this.memberTable.selectedRows.length === 1) {
|
if (this.memberTable.selectedRows.length === 1) {
|
||||||
this.removeMember(this.memberTable.selectedRows[0]);
|
await this.removeMember(this.memberTable.selectedRows[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.memberSection = this.createGroup(localizedConstants.MemberSectionHeader, [this.memberTable, buttonContainer]);
|
this.memberSection = this.createGroup(localizedConstants.MemberSectionHeader, [this.memberTable, buttonContainer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addMembers(names: string[]): void {
|
private async addMembers(names: string[]): Promise<void> {
|
||||||
names.forEach(n => {
|
names.forEach(n => {
|
||||||
if (this.objectInfo.members.indexOf(n) === -1) {
|
if (this.objectInfo.members.indexOf(n) === -1) {
|
||||||
this.objectInfo.members.push(n);
|
this.objectInfo.members.push(n);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.updateMembersTable();
|
await this.updateMembersTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeMember(idx: number): void {
|
private async removeMember(idx: number): Promise<void> {
|
||||||
this.objectInfo.members.splice(idx, 1);
|
this.objectInfo.members.splice(idx, 1);
|
||||||
this.updateMembersTable();
|
await this.updateMembersTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateMembersTable(): void {
|
private async updateMembersTable(): Promise<void> {
|
||||||
this.setTableData(this.memberTable, this.objectInfo.members.map(m => [m]));
|
await this.setTableData(this.memberTable, this.objectInfo.members.map(m => [m]));
|
||||||
this.onFormFieldChange();
|
this.onFormFieldChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ export class DatabaseRoleDialog extends ObjectManagementDialogBase<ObjectManagem
|
|||||||
[localizedConstants.SchemaText],
|
[localizedConstants.SchemaText],
|
||||||
this.viewInfo.schemas,
|
this.viewInfo.schemas,
|
||||||
this.objectInfo.ownedSchemas,
|
this.objectInfo.ownedSchemas,
|
||||||
DefaultMaxTableHeight,
|
DefaultMaxTableRowCount,
|
||||||
(item) => {
|
(item) => {
|
||||||
// It is not allowed to have unassigned schema.
|
// It is not allowed to have unassigned schema.
|
||||||
return this.objectInfo.ownedSchemas.indexOf(item) === -1;
|
return this.objectInfo.ownedSchemas.indexOf(item) === -1;
|
||||||
|
|||||||
@@ -5,15 +5,19 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as mssql from 'mssql';
|
import * as mssql from 'mssql';
|
||||||
import { DefaultTableListItemEnabledStateGetter, DefaultMaxTableHeight, DialogBase, TableListItemComparer, TableListItemValueGetter } from '../../ui/dialogBase';
|
import { DefaultTableListItemEnabledStateGetter, DefaultMaxTableRowCount, DialogBase, TableListItemComparer } from '../../ui/dialogBase';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { getErrorMessage } from '../../utils';
|
import { getErrorMessage } from '../../utils';
|
||||||
|
|
||||||
|
type ObjectType = string | { name: string, displayName: string };
|
||||||
|
|
||||||
export interface FindObjectDialogOptions {
|
export interface FindObjectDialogOptions {
|
||||||
objectTypes: mssql.ObjectManagement.NodeType[];
|
objectTypes: ObjectType[];
|
||||||
|
selectAllObjectTypes: boolean;
|
||||||
multiSelect: boolean;
|
multiSelect: boolean;
|
||||||
contextId: string;
|
contextId: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
showSchemaColumn?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FindObjectDialogResult {
|
export interface FindObjectDialogResult {
|
||||||
@@ -22,15 +26,10 @@ export interface FindObjectDialogResult {
|
|||||||
|
|
||||||
const ObjectComparer: TableListItemComparer<mssql.ObjectManagement.SearchResultItem> =
|
const ObjectComparer: TableListItemComparer<mssql.ObjectManagement.SearchResultItem> =
|
||||||
(item1, item2) => {
|
(item1, item2) => {
|
||||||
return item1.name === item2.name && item1.type === item2.type;
|
return item1.name === item2.name && item1.type === item2.type && item1.schema === item2.schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ObjectRowValueGetter: TableListItemValueGetter<mssql.ObjectManagement.SearchResultItem> =
|
const ObjectsTableMaxRowCount = 20;
|
||||||
(item) => {
|
|
||||||
return [item.name, localizedConstants.getNodeTypeDisplayName(item.type, true)];
|
|
||||||
};
|
|
||||||
|
|
||||||
const ObjectsTableMaxHeight = 700;
|
|
||||||
|
|
||||||
export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
||||||
private objectTypesTable: azdata.TableComponent;
|
private objectTypesTable: azdata.TableComponent;
|
||||||
@@ -38,7 +37,7 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
|||||||
private objectsTable: azdata.TableComponent;
|
private objectsTable: azdata.TableComponent;
|
||||||
private objectsLoadingComponent: azdata.LoadingComponent;
|
private objectsLoadingComponent: azdata.LoadingComponent;
|
||||||
private result: FindObjectDialogResult;
|
private result: FindObjectDialogResult;
|
||||||
private selectedObjectTypes: string[] = [];
|
private selectedObjectTypes: ObjectType[] = [];
|
||||||
private allObjects: mssql.ObjectManagement.SearchResultItem[] = [];
|
private allObjects: mssql.ObjectManagement.SearchResultItem[] = [];
|
||||||
|
|
||||||
constructor(private readonly objectManagementService: mssql.IObjectManagementService, private readonly options: FindObjectDialogOptions) {
|
constructor(private readonly objectManagementService: mssql.IObjectManagementService, private readonly options: FindObjectDialogOptions) {
|
||||||
@@ -47,40 +46,52 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
|||||||
this.result = {
|
this.result = {
|
||||||
selectedObjects: []
|
selectedObjects: []
|
||||||
};
|
};
|
||||||
this.selectedObjectTypes = [...options.objectTypes];
|
this.selectedObjectTypes = options.selectAllObjectTypes ? [...options.objectTypes] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private getObjectTypeName(objectType: ObjectType): string {
|
||||||
|
return typeof objectType === 'string' ? objectType : objectType.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getObjectTypeDisplayName(objectType: ObjectType): string {
|
||||||
|
return typeof objectType === 'string' ? localizedConstants.getNodeTypeDisplayName(objectType, true) : objectType.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async initialize(): Promise<void> {
|
protected override async initialize(): Promise<void> {
|
||||||
this.dialogObject.okButton.enabled = false;
|
this.dialogObject.okButton.enabled = false;
|
||||||
this.objectTypesTable = this.createTableList<string>(localizedConstants.ObjectTypeText,
|
this.objectTypesTable = this.createTableList<ObjectType>(localizedConstants.ObjectTypeText,
|
||||||
[localizedConstants.ObjectTypeText],
|
[localizedConstants.ObjectTypeText],
|
||||||
this.options.objectTypes,
|
this.options.objectTypes,
|
||||||
this.selectedObjectTypes,
|
this.selectedObjectTypes,
|
||||||
DefaultMaxTableHeight,
|
DefaultMaxTableRowCount,
|
||||||
DefaultTableListItemEnabledStateGetter, (item) => {
|
DefaultTableListItemEnabledStateGetter, (item) => {
|
||||||
return [localizedConstants.getNodeTypeDisplayName(item, true)];
|
return [this.getObjectTypeDisplayName(item)];
|
||||||
|
}, (item1, item2) => {
|
||||||
|
return this.getObjectTypeName(item1) === this.getObjectTypeName(item2);
|
||||||
});
|
});
|
||||||
this.findButton = this.createButton(localizedConstants.FindText, localizedConstants.FindText, async () => {
|
this.findButton = this.createButton(localizedConstants.FindText, localizedConstants.FindText, async () => {
|
||||||
await this.onFindObjectButtonClick();
|
await this.onFindObjectButtonClick();
|
||||||
});
|
}, this.options.selectAllObjectTypes);
|
||||||
const buttonContainer = this.createButtonContainer([this.findButton]);
|
const buttonContainer = this.createButtonContainer([this.findButton]);
|
||||||
const objectTypeSection = this.createGroup(localizedConstants.ObjectTypeText, [this.objectTypesTable, buttonContainer]);
|
const objectTypeSection = this.createGroup(localizedConstants.ObjectTypeText, [this.objectTypesTable, buttonContainer]);
|
||||||
|
const columns = [localizedConstants.NameText, localizedConstants.ObjectTypeText];
|
||||||
|
if (this.options.showSchemaColumn) {
|
||||||
|
columns.splice(1, 0, localizedConstants.SchemaText);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.options.multiSelect) {
|
if (this.options.multiSelect) {
|
||||||
this.objectsTable = this.createTableList<mssql.ObjectManagement.SearchResultItem>(localizedConstants.ObjectsText,
|
this.objectsTable = this.createTableList<mssql.ObjectManagement.SearchResultItem>(localizedConstants.ObjectsText,
|
||||||
[localizedConstants.NameText, localizedConstants.ObjectTypeText],
|
columns,
|
||||||
this.allObjects,
|
this.allObjects,
|
||||||
this.result.selectedObjects,
|
this.result.selectedObjects,
|
||||||
ObjectsTableMaxHeight,
|
ObjectsTableMaxRowCount,
|
||||||
DefaultTableListItemEnabledStateGetter,
|
DefaultTableListItemEnabledStateGetter,
|
||||||
ObjectRowValueGetter,
|
(item) => {
|
||||||
|
return this.getObjectRowValue(item);
|
||||||
|
},
|
||||||
ObjectComparer);
|
ObjectComparer);
|
||||||
} else {
|
} else {
|
||||||
this.objectsTable = this.createTable(localizedConstants.ObjectsText, [{
|
this.objectsTable = this.createTable(localizedConstants.ObjectsText, columns, [], ObjectsTableMaxRowCount);
|
||||||
value: localizedConstants.NameText,
|
|
||||||
}, {
|
|
||||||
value: localizedConstants.ObjectTypeText
|
|
||||||
}], []);
|
|
||||||
this.disposables.push(this.objectsTable.onRowSelected(async () => {
|
this.disposables.push(this.objectsTable.onRowSelected(async () => {
|
||||||
if (this.objectsTable.selectedRows.length > 0) {
|
if (this.objectsTable.selectedRows.length > 0) {
|
||||||
this.result.selectedObjects = [this.allObjects[this.objectsTable.selectedRows[0]]];
|
this.result.selectedObjects = [this.allObjects[this.objectsTable.selectedRows[0]]];
|
||||||
@@ -95,7 +106,7 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
|||||||
}).component();
|
}).component();
|
||||||
const objectsSection = this.createGroup(localizedConstants.ObjectsText, [this.objectsLoadingComponent]);
|
const objectsSection = this.createGroup(localizedConstants.ObjectsText, [this.objectsLoadingComponent]);
|
||||||
|
|
||||||
this.formContainer.addItems([objectTypeSection, objectsSection]);
|
this.formContainer.addItems([objectTypeSection, objectsSection], this.getSectionItemLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override get dialogResult(): FindObjectDialogResult | undefined {
|
protected override get dialogResult(): FindObjectDialogResult | undefined {
|
||||||
@@ -107,16 +118,18 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
|||||||
this.objectsLoadingComponent.loading = true;
|
this.objectsLoadingComponent.loading = true;
|
||||||
this.findButton.enabled = false;
|
this.findButton.enabled = false;
|
||||||
try {
|
try {
|
||||||
const results = await this.objectManagementService.search(this.options.contextId, <mssql.ObjectManagement.NodeType[]>this.selectedObjectTypes);
|
const results = await this.objectManagementService.search(this.options.contextId, this.selectedObjectTypes.map(item => this.getObjectTypeName(item)));
|
||||||
this.allObjects.splice(0, this.allObjects.length, ...results);
|
this.allObjects.splice(0, this.allObjects.length, ...results);
|
||||||
let data;
|
let data;
|
||||||
if (this.options.multiSelect) {
|
if (this.options.multiSelect) {
|
||||||
data = this.getDataForTableList(this.allObjects, this.result.selectedObjects, DefaultTableListItemEnabledStateGetter, ObjectRowValueGetter, ObjectComparer);
|
data = this.getDataForTableList(this.allObjects, this.result.selectedObjects, DefaultTableListItemEnabledStateGetter, (item) => {
|
||||||
|
return this.getObjectRowValue(item);
|
||||||
|
}, ObjectComparer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data = this.allObjects.map(item => ObjectRowValueGetter(item));
|
data = this.allObjects.map(item => { return this.getObjectRowValue(item); });
|
||||||
}
|
}
|
||||||
this.setTableData(this.objectsTable, data, ObjectsTableMaxHeight);
|
await this.setTableData(this.objectsTable, data, ObjectsTableMaxRowCount);
|
||||||
this.objectsLoadingComponent.loadingCompletedText = localizedConstants.LoadingObjectsCompletedText(results.length);
|
this.objectsLoadingComponent.loadingCompletedText = localizedConstants.LoadingObjectsCompletedText(results.length);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.dialogObject.message = {
|
this.dialogObject.message = {
|
||||||
@@ -132,4 +145,12 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
|||||||
this.findButton.enabled = this.selectedObjectTypes.length > 0;
|
this.findButton.enabled = this.selectedObjectTypes.length > 0;
|
||||||
this.dialogObject.okButton.enabled = this.result.selectedObjects.length > 0;
|
this.dialogObject.okButton.enabled = this.result.selectedObjects.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getObjectRowValue(item: mssql.ObjectManagement.SearchResultItem): string[] {
|
||||||
|
const row = [item.name, this.getObjectTypeName(item.type)];
|
||||||
|
if (this.options.showSchemaColumn) {
|
||||||
|
row.splice(1, 0, item.schema);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,16 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||||
import * as objectManagementLoc from '../localizedConstants';
|
import * as objectManagementLoc from '../localizedConstants';
|
||||||
import * as uiLoc from '../../ui/localizedConstants';
|
import * as uiLoc from '../../ui/localizedConstants';
|
||||||
import { AlterLoginDocUrl, CreateLoginDocUrl, PublicServerRoleName } from '../constants';
|
import { AlterLoginDocUrl, CreateLoginDocUrl, PublicServerRoleName } from '../constants';
|
||||||
import { isValidSQLPassword } from '../utils';
|
import { isValidSQLPassword } from '../utils';
|
||||||
import { DefaultMaxTableHeight } from '../../ui/dialogBase';
|
import { DefaultMaxTableRowCount } from '../../ui/dialogBase';
|
||||||
|
import { PrincipalDialogBase } from './principalDialogBase';
|
||||||
|
|
||||||
export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Login, ObjectManagement.LoginViewInfo> {
|
export class LoginDialog extends PrincipalDialogBase<ObjectManagement.Login, ObjectManagement.LoginViewInfo> {
|
||||||
private generalSection: azdata.GroupContainer;
|
private generalSection: azdata.GroupContainer;
|
||||||
private sqlAuthSection: azdata.GroupContainer;
|
private sqlAuthSection: azdata.GroupContainer;
|
||||||
private serverRoleSection: azdata.GroupContainer;
|
private serverRoleSection: azdata.GroupContainer;
|
||||||
@@ -34,7 +35,7 @@ export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Log
|
|||||||
private lockedOutCheckbox: azdata.CheckBoxComponent;
|
private lockedOutCheckbox: azdata.CheckBoxComponent;
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
super(objectManagementService, options);
|
super(objectManagementService, options, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override get helpUrl(): string {
|
protected override get helpUrl(): string {
|
||||||
@@ -82,7 +83,8 @@ export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Log
|
|||||||
this.objectInfo.password = this.objectInfo.password ?? '';
|
this.objectInfo.password = this.objectInfo.password ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeUI(): Promise<void> {
|
protected override async initializeUI(): Promise<void> {
|
||||||
|
await super.initializeUI();
|
||||||
const sections: azdata.Component[] = [];
|
const sections: azdata.Component[] = [];
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
sections.push(this.generalSection);
|
sections.push(this.generalSection);
|
||||||
@@ -94,12 +96,13 @@ export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Log
|
|||||||
|
|
||||||
this.initializeServerRolesSection();
|
this.initializeServerRolesSection();
|
||||||
sections.push(this.serverRoleSection);
|
sections.push(this.serverRoleSection);
|
||||||
|
sections.push(this.securableSection);
|
||||||
|
|
||||||
if (this.viewInfo.supportAdvancedOptions) {
|
if (this.viewInfo.supportAdvancedOptions) {
|
||||||
this.initializeAdvancedSection();
|
this.initializeAdvancedSection();
|
||||||
sections.push(this.advancedSection);
|
sections.push(this.advancedSection);
|
||||||
}
|
}
|
||||||
this.formContainer.addItems(sections);
|
this.formContainer.addItems(sections, this.getSectionItemLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeGeneralSection(): void {
|
private initializeGeneralSection(): void {
|
||||||
@@ -203,7 +206,7 @@ export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Log
|
|||||||
items.push(defaultDatabaseContainer, defaultLanguageContainer, this.connectPermissionCheckbox);
|
items.push(defaultDatabaseContainer, defaultLanguageContainer, this.connectPermissionCheckbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.advancedSection = this.createGroup(objectManagementLoc.AdvancedSectionHeader, items);
|
this.advancedSection = this.createGroup(objectManagementLoc.AdvancedSectionHeader, items, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeServerRolesSection(): void {
|
private initializeServerRolesSection(): void {
|
||||||
@@ -211,7 +214,7 @@ export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Log
|
|||||||
[objectManagementLoc.ServerRoleTypeDisplayNameInTitle],
|
[objectManagementLoc.ServerRoleTypeDisplayNameInTitle],
|
||||||
this.viewInfo.serverRoles,
|
this.viewInfo.serverRoles,
|
||||||
this.objectInfo.serverRoles,
|
this.objectInfo.serverRoles,
|
||||||
DefaultMaxTableHeight,
|
DefaultMaxTableRowCount,
|
||||||
(item) => {
|
(item) => {
|
||||||
return item !== PublicServerRoleName
|
return item !== PublicServerRoleName
|
||||||
});
|
});
|
||||||
@@ -220,7 +223,7 @@ export class LoginDialog extends ObjectManagementDialogBase<ObjectManagement.Log
|
|||||||
|
|
||||||
private setViewByAuthenticationType(): void {
|
private setViewByAuthenticationType(): void {
|
||||||
if (this.authTypeDropdown.value === objectManagementLoc.SQLAuthenticationTypeDisplayText) {
|
if (this.authTypeDropdown.value === objectManagementLoc.SQLAuthenticationTypeDisplayText) {
|
||||||
this.addItem(this.formContainer, this.sqlAuthSection, 1);
|
this.addItem(this.formContainer, this.sqlAuthSection, this.getSectionItemLayout(), 1);
|
||||||
} else if (this.authTypeDropdown.value !== objectManagementLoc.SQLAuthenticationTypeDisplayText) {
|
} else if (this.authTypeDropdown.value !== objectManagementLoc.SQLAuthenticationTypeDisplayText) {
|
||||||
this.removeItem(this.formContainer, this.sqlAuthSection);
|
this.removeItem(this.formContainer, this.sqlAuthSection);
|
||||||
}
|
}
|
||||||
|
|||||||
228
extensions/mssql/src/objectManagement/ui/principalDialogBase.ts
Normal file
228
extensions/mssql/src/objectManagement/ui/principalDialogBase.ts
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
import * as mssql from 'mssql';
|
||||||
|
import * as localizedConstants from '../localizedConstants';
|
||||||
|
|
||||||
|
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
|
import { FindObjectDialog } from './findObjectDialog';
|
||||||
|
import { deepClone } from '../../util/objects';
|
||||||
|
import { DefaultTableWidth, getTableHeight } from '../../ui/dialogBase';
|
||||||
|
|
||||||
|
const GrantColumnIndex = 2;
|
||||||
|
const WithGrantColumnIndex = 3;
|
||||||
|
const DenyColumnIndex = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for security principal dialogs such as user, role, etc.
|
||||||
|
*/
|
||||||
|
export abstract class PrincipalDialogBase<ObjectInfoType extends mssql.ObjectManagement.SecurityPrincipalObject, ViewInfoType extends mssql.ObjectManagement.SecurityPrincipalViewInfo<ObjectInfoType>> extends ObjectManagementDialogBase<ObjectInfoType, ViewInfoType> {
|
||||||
|
protected securableTable: azdata.TableComponent;
|
||||||
|
protected permissionTable: azdata.TableComponent;
|
||||||
|
protected effectivePermissionTable: azdata.TableComponent;
|
||||||
|
protected securableSection: azdata.GroupContainer;
|
||||||
|
protected explicitPermissionTableLabel: azdata.TextComponent;
|
||||||
|
protected effectivePermissionTableLabel: azdata.TextComponent;
|
||||||
|
private securablePermissions: mssql.ObjectManagement.SecurablePermissions[] = [];
|
||||||
|
|
||||||
|
constructor(objectManagementService: mssql.IObjectManagementService, options: ObjectManagementDialogOptions, private readonly showSchemaColumn: boolean, private readonly supportEffectivePermissions: boolean = true) {
|
||||||
|
super(objectManagementService, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async initializeUI(): Promise<void> {
|
||||||
|
this.securablePermissions = deepClone(this.objectInfo.securablePermissions);
|
||||||
|
this.initializeSecurableSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeSecurableSection(): void {
|
||||||
|
const items: azdata.Component[] = [];
|
||||||
|
const securableTableColumns = [localizedConstants.NameText, localizedConstants.ObjectTypeText];
|
||||||
|
if (this.showSchemaColumn) {
|
||||||
|
securableTableColumns.splice(1, 0, localizedConstants.SchemaText);
|
||||||
|
}
|
||||||
|
this.securableTable = this.createTable(localizedConstants.SecurablesText, securableTableColumns, this.getSecurableTableData());
|
||||||
|
const buttonContainer = this.addButtonsForTable(this.securableTable, localizedConstants.AddSecurableAriaLabel, localizedConstants.RemoveSecurableAriaLabel,
|
||||||
|
() => this.onAddSecurableButtonClicked(), () => this.onRemoveSecurableButtonClicked());
|
||||||
|
this.disposables.push(this.securableTable.onRowSelected(async () => {
|
||||||
|
await this.updatePermissionsTable();
|
||||||
|
}));
|
||||||
|
this.explicitPermissionTableLabel = this.modelView.modelBuilder.text().withProps({ value: localizedConstants.ExplicitPermissionsTableLabel }).component();
|
||||||
|
this.permissionTable = this.modelView.modelBuilder.table().withProps({
|
||||||
|
ariaLabel: localizedConstants.ExplicitPermissionsTableLabel,
|
||||||
|
columns:
|
||||||
|
[{
|
||||||
|
type: azdata.ColumnType.text,
|
||||||
|
value: localizedConstants.PermissionColumnHeader
|
||||||
|
}, {
|
||||||
|
type: azdata.ColumnType.text,
|
||||||
|
value: localizedConstants.GrantorColumnHeader
|
||||||
|
}, {
|
||||||
|
type: azdata.ColumnType.checkBox,
|
||||||
|
value: localizedConstants.GrantColumnHeader
|
||||||
|
}, {
|
||||||
|
type: azdata.ColumnType.checkBox,
|
||||||
|
value: localizedConstants.WithGrantColumnHeader
|
||||||
|
}, {
|
||||||
|
type: azdata.ColumnType.checkBox,
|
||||||
|
value: localizedConstants.DenyColumnHeader
|
||||||
|
}],
|
||||||
|
data: [],
|
||||||
|
height: getTableHeight(0),
|
||||||
|
width: DefaultTableWidth
|
||||||
|
}).component();
|
||||||
|
this.disposables.push(this.permissionTable.onCellAction(async (arg: azdata.ICheckboxCellActionEventArgs) => {
|
||||||
|
const permissionName = this.permissionTable.data[arg.row][0];
|
||||||
|
const securable = this.securablePermissions[this.securableTable.selectedRows[0]];
|
||||||
|
let permission: mssql.ObjectManagement.SecurablePermissionItem = securable.permissions.find(securablePermission => securablePermission.permission === permissionName);
|
||||||
|
if (!permission) {
|
||||||
|
permission = {
|
||||||
|
permission: permissionName,
|
||||||
|
grantor: ''
|
||||||
|
};
|
||||||
|
securable.permissions.push(permission);
|
||||||
|
}
|
||||||
|
if (arg.column === GrantColumnIndex) {
|
||||||
|
permission.grant = arg.checked ? true : undefined;
|
||||||
|
if (!arg.checked) {
|
||||||
|
permission.withGrant = undefined;
|
||||||
|
}
|
||||||
|
} else if (arg.column === WithGrantColumnIndex) {
|
||||||
|
permission.withGrant = arg.checked ? true : undefined;
|
||||||
|
if (arg.checked) {
|
||||||
|
permission.grant = true;
|
||||||
|
}
|
||||||
|
} else if (arg.column === DenyColumnIndex) {
|
||||||
|
permission.grant = arg.checked ? false : undefined;
|
||||||
|
if (arg.checked) {
|
||||||
|
permission.withGrant = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.updatePermissionsTable();
|
||||||
|
this.updateSecurablePermissions();
|
||||||
|
// Restore the focus to previously selected cell.
|
||||||
|
this.permissionTable.setActiveCell(arg.row, arg.column);
|
||||||
|
}));
|
||||||
|
|
||||||
|
items.push(this.securableTable, buttonContainer, this.explicitPermissionTableLabel, this.permissionTable);
|
||||||
|
if (this.showEffectivePermissions) {
|
||||||
|
this.effectivePermissionTableLabel = this.modelView.modelBuilder.text().withProps({ value: localizedConstants.EffectivePermissionsTableLabel }).component();
|
||||||
|
this.effectivePermissionTable = this.createTable(localizedConstants.EffectivePermissionsTableLabel, [localizedConstants.PermissionColumnHeader], []);
|
||||||
|
items.push(this.effectivePermissionTableLabel, this.effectivePermissionTable);
|
||||||
|
}
|
||||||
|
this.securableSection = this.createGroup(localizedConstants.SecurablesText, items, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async onAddSecurableButtonClicked(): Promise<void> {
|
||||||
|
const dialog = new FindObjectDialog(this.objectManagementService, {
|
||||||
|
objectTypes: this.viewInfo.supportedSecurableTypes,
|
||||||
|
selectAllObjectTypes: false,
|
||||||
|
multiSelect: true,
|
||||||
|
contextId: this.contextId,
|
||||||
|
title: localizedConstants.SelectSecurablesDialogTitle,
|
||||||
|
showSchemaColumn: this.showSchemaColumn
|
||||||
|
});
|
||||||
|
await dialog.open();
|
||||||
|
const result = await dialog.waitForClose();
|
||||||
|
if (result && result.selectedObjects.length > 0) {
|
||||||
|
result.selectedObjects.forEach(obj => {
|
||||||
|
if (this.securablePermissions.find(securable => securable.type === obj.type && securable.name === obj.name && securable.schema === obj.schema)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const securableTypeMetadata = this.viewInfo.supportedSecurableTypes.find(securableType => securableType.name === obj.type);
|
||||||
|
this.securablePermissions.push({
|
||||||
|
name: obj.name,
|
||||||
|
schema: obj.schema,
|
||||||
|
type: obj.type,
|
||||||
|
permissions: securableTypeMetadata.permissions.map(permission => {
|
||||||
|
return {
|
||||||
|
permission: permission.name,
|
||||||
|
grantor: '',
|
||||||
|
grant: undefined,
|
||||||
|
withGrant: undefined
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
effectivePermissions: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const data = this.getSecurableTableData();
|
||||||
|
await this.setTableData(this.securableTable, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async onRemoveSecurableButtonClicked(): Promise<void> {
|
||||||
|
if (this.securableTable.selectedRows.length === 1) {
|
||||||
|
this.securablePermissions.splice(this.securableTable.selectedRows[0], 1);
|
||||||
|
const data = this.getSecurableTableData();
|
||||||
|
await this.setTableData(this.securableTable, data);
|
||||||
|
this.updateSecurablePermissions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSecurableTableData(): string[][] {
|
||||||
|
return this.securablePermissions.map(securable => {
|
||||||
|
const row = [securable.name, this.getSecurableTypeDisplayName(securable.type)];
|
||||||
|
if (this.showSchemaColumn) {
|
||||||
|
row.splice(1, 0, securable.schema);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updatePermissionsTable(): Promise<void> {
|
||||||
|
let permissionsTableData: any[][] = [];
|
||||||
|
let effectivePermissionsTableData: any[][] = [];
|
||||||
|
let explicitPermissionsLabel = localizedConstants.ExplicitPermissionsTableLabel;
|
||||||
|
let effectivePermissionsLabel = localizedConstants.EffectivePermissionsTableLabel;
|
||||||
|
if (this.securableTable.selectedRows.length === 1) {
|
||||||
|
const securable = this.securablePermissions[this.securableTable.selectedRows[0]];
|
||||||
|
if (securable) {
|
||||||
|
const securableDisplayName = securable.schema ? `${securable.schema}.${securable.name}` : securable.name;
|
||||||
|
explicitPermissionsLabel = localizedConstants.ExplicitPermissionsTableLabelSelected(securableDisplayName);
|
||||||
|
effectivePermissionsLabel = localizedConstants.EffectivePermissionsTableLabelSelected(securableDisplayName);
|
||||||
|
const securableTypeMetadata = this.viewInfo.supportedSecurableTypes.find(securableType => securableType.name === securable.type);
|
||||||
|
permissionsTableData = securable.permissions.map(permission => {
|
||||||
|
return [permission.permission, permission.grantor, { checked: permission.grant === true }, { checked: permission.withGrant === true }, { checked: permission.grant === false }];
|
||||||
|
});
|
||||||
|
permissionsTableData = securableTypeMetadata.permissions.map(permissionMetadata => {
|
||||||
|
const permission = securable.permissions.find(securablePermission => securablePermission.permission === permissionMetadata.name);
|
||||||
|
return [
|
||||||
|
permissionMetadata.name,
|
||||||
|
permission?.grantor ?? '',
|
||||||
|
{ checked: permission?.grant === true },
|
||||||
|
{ checked: permission?.withGrant === true },
|
||||||
|
{ checked: permission?.grant === false }];
|
||||||
|
});
|
||||||
|
effectivePermissionsTableData = securable.effectivePermissions.map(permission => [permission]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.explicitPermissionTableLabel.value = explicitPermissionsLabel;
|
||||||
|
await this.setTableData(this.permissionTable, permissionsTableData);
|
||||||
|
if (this.showEffectivePermissions) {
|
||||||
|
this.effectivePermissionTableLabel.value = effectivePermissionsLabel;
|
||||||
|
await this.setTableData(this.effectivePermissionTable, effectivePermissionsTableData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateSecurablePermissions(): void {
|
||||||
|
// Only save securable permissions that have grant or deny value.
|
||||||
|
this.objectInfo.securablePermissions = deepClone(this.securablePermissions.filter((securablePermissions) => {
|
||||||
|
return securablePermissions.permissions.some(permission => permission.grant !== undefined);
|
||||||
|
}));
|
||||||
|
this.objectInfo.securablePermissions.forEach(securablePermissions => {
|
||||||
|
securablePermissions.permissions = securablePermissions.permissions.filter(permission => permission.grant !== undefined);
|
||||||
|
});
|
||||||
|
this.onFormFieldChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSecurableTypeDisplayName(securableType: string): string {
|
||||||
|
const securableTypeMetadata = this.viewInfo.supportedSecurableTypes.find(securableTypeMetadata => securableTypeMetadata.name === securableType);
|
||||||
|
return securableTypeMetadata ? securableTypeMetadata.displayName : securableType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get showEffectivePermissions(): boolean {
|
||||||
|
return !this.options.isNewObject && this.supportEffectivePermissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,13 +3,14 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { AlterServerRoleDocUrl, CreateServerRoleDocUrl } from '../constants';
|
import { AlterServerRoleDocUrl, CreateServerRoleDocUrl } from '../constants';
|
||||||
import { FindObjectDialog } from './findObjectDialog';
|
import { FindObjectDialog } from './findObjectDialog';
|
||||||
|
import { PrincipalDialogBase } from './principalDialogBase';
|
||||||
|
|
||||||
export class ServerRoleDialog extends ObjectManagementDialogBase<ObjectManagement.ServerRoleInfo, ObjectManagement.ServerRoleViewInfo> {
|
export class ServerRoleDialog extends PrincipalDialogBase<ObjectManagement.ServerRoleInfo, ObjectManagement.ServerRoleViewInfo> {
|
||||||
// Sections
|
// Sections
|
||||||
private generalSection: azdata.GroupContainer;
|
private generalSection: azdata.GroupContainer;
|
||||||
private membershipSection: azdata.GroupContainer;
|
private membershipSection: azdata.GroupContainer;
|
||||||
@@ -27,22 +28,24 @@ export class ServerRoleDialog extends ObjectManagementDialogBase<ObjectManagemen
|
|||||||
|
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
super(objectManagementService, options);
|
super(objectManagementService, options, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override get helpUrl(): string {
|
protected override get helpUrl(): string {
|
||||||
return this.options.isNewObject ? CreateServerRoleDocUrl : AlterServerRoleDocUrl;
|
return this.options.isNewObject ? CreateServerRoleDocUrl : AlterServerRoleDocUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeUI(): Promise<void> {
|
protected override async initializeUI(): Promise<void> {
|
||||||
|
await super.initializeUI();
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
this.initializeMemberSection();
|
this.initializeMemberSection();
|
||||||
const sections: azdata.Component[] = [this.generalSection, this.memberSection];
|
const sections: azdata.Component[] = [this.generalSection, this.memberSection];
|
||||||
if (!this.viewInfo.isFixedRole) {
|
if (!this.viewInfo.isFixedRole) {
|
||||||
this.initializeMembershipSection();
|
this.initializeMembershipSection();
|
||||||
sections.push(this.membershipSection);
|
sections.push(this.membershipSection);
|
||||||
|
sections.push(this.securableSection);
|
||||||
}
|
}
|
||||||
this.formContainer.addItems(sections);
|
this.formContainer.addItems(sections, this.getSectionItemLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeGeneralSection(): void {
|
private initializeGeneralSection(): void {
|
||||||
@@ -57,6 +60,7 @@ export class ServerRoleDialog extends ObjectManagementDialogBase<ObjectManagemen
|
|||||||
const browseOwnerButton = this.createButton(localizedConstants.BrowseText, localizedConstants.BrowseOwnerButtonAriaLabel, async () => {
|
const browseOwnerButton = this.createButton(localizedConstants.BrowseText, localizedConstants.BrowseOwnerButtonAriaLabel, async () => {
|
||||||
const dialog = new FindObjectDialog(this.objectManagementService, {
|
const dialog = new FindObjectDialog(this.objectManagementService, {
|
||||||
objectTypes: [ObjectManagement.NodeType.ServerLevelLogin, ObjectManagement.NodeType.ServerLevelServerRole],
|
objectTypes: [ObjectManagement.NodeType.ServerLevelLogin, ObjectManagement.NodeType.ServerLevelServerRole],
|
||||||
|
selectAllObjectTypes: true,
|
||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
contextId: this.contextId,
|
contextId: this.contextId,
|
||||||
title: localizedConstants.SelectServerRoleOwnerDialogTitle
|
title: localizedConstants.SelectServerRoleOwnerDialogTitle
|
||||||
@@ -76,48 +80,44 @@ export class ServerRoleDialog extends ObjectManagementDialogBase<ObjectManagemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeMemberSection(): void {
|
private initializeMemberSection(): void {
|
||||||
this.memberTable = this.createTable(localizedConstants.MemberSectionHeader, [
|
this.memberTable = this.createTable(localizedConstants.MemberSectionHeader, [localizedConstants.NameText], this.objectInfo.members.map(m => [m]));
|
||||||
{
|
|
||||||
type: azdata.ColumnType.text,
|
|
||||||
value: localizedConstants.NameText
|
|
||||||
}
|
|
||||||
], this.objectInfo.members.map(m => [m]));
|
|
||||||
const buttonContainer = this.addButtonsForTable(this.memberTable, localizedConstants.AddMemberAriaLabel, localizedConstants.RemoveMemberAriaLabel,
|
const buttonContainer = this.addButtonsForTable(this.memberTable, localizedConstants.AddMemberAriaLabel, localizedConstants.RemoveMemberAriaLabel,
|
||||||
async () => {
|
async () => {
|
||||||
const dialog = new FindObjectDialog(this.objectManagementService, {
|
const dialog = new FindObjectDialog(this.objectManagementService, {
|
||||||
objectTypes: [ObjectManagement.NodeType.ServerLevelLogin, ObjectManagement.NodeType.ServerLevelServerRole],
|
objectTypes: [ObjectManagement.NodeType.ServerLevelLogin, ObjectManagement.NodeType.ServerLevelServerRole],
|
||||||
|
selectAllObjectTypes: true,
|
||||||
multiSelect: true,
|
multiSelect: true,
|
||||||
contextId: this.contextId,
|
contextId: this.contextId,
|
||||||
title: localizedConstants.SelectServerRoleMemberDialogTitle
|
title: localizedConstants.SelectServerRoleMemberDialogTitle
|
||||||
});
|
});
|
||||||
await dialog.open();
|
await dialog.open();
|
||||||
const result = await dialog.waitForClose();
|
const result = await dialog.waitForClose();
|
||||||
this.addMembers(result.selectedObjects.map(r => r.name));
|
await this.addMembers(result.selectedObjects.map(r => r.name));
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
if (this.memberTable.selectedRows.length === 1) {
|
if (this.memberTable.selectedRows.length === 1) {
|
||||||
this.removeMember(this.memberTable.selectedRows[0]);
|
await this.removeMember(this.memberTable.selectedRows[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.memberSection = this.createGroup(localizedConstants.MemberSectionHeader, [this.memberTable, buttonContainer]);
|
this.memberSection = this.createGroup(localizedConstants.MemberSectionHeader, [this.memberTable, buttonContainer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addMembers(names: string[]): void {
|
private async addMembers(names: string[]): Promise<void> {
|
||||||
names.forEach(n => {
|
names.forEach(n => {
|
||||||
if (this.objectInfo.members.indexOf(n) === -1) {
|
if (this.objectInfo.members.indexOf(n) === -1) {
|
||||||
this.objectInfo.members.push(n);
|
this.objectInfo.members.push(n);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.updateMembersTable();
|
await this.updateMembersTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeMember(idx: number): void {
|
private async removeMember(idx: number): Promise<void> {
|
||||||
this.objectInfo.members.splice(idx, 1);
|
this.objectInfo.members.splice(idx, 1);
|
||||||
this.updateMembersTable();
|
await this.updateMembersTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateMembersTable(): void {
|
private async updateMembersTable(): Promise<void> {
|
||||||
this.setTableData(this.memberTable, this.objectInfo.members.map(m => [m]));
|
await this.setTableData(this.memberTable, this.objectInfo.members.map(m => [m]));
|
||||||
this.onFormFieldChange();
|
this.onFormFieldChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { AlterUserDocUrl, CreateUserDocUrl } from '../constants';
|
import { AlterUserDocUrl, CreateUserDocUrl } from '../constants';
|
||||||
import { isValidSQLPassword } from '../utils';
|
import { isValidSQLPassword } from '../utils';
|
||||||
import { DefaultMaxTableHeight } from '../../ui/dialogBase';
|
import { DefaultMaxTableRowCount } from '../../ui/dialogBase';
|
||||||
|
import { PrincipalDialogBase } from './principalDialogBase';
|
||||||
|
|
||||||
export class UserDialog extends ObjectManagementDialogBase<ObjectManagement.User, ObjectManagement.UserViewInfo> {
|
export class UserDialog extends PrincipalDialogBase<ObjectManagement.User, ObjectManagement.UserViewInfo> {
|
||||||
private generalSection: azdata.GroupContainer;
|
private generalSection: azdata.GroupContainer;
|
||||||
private ownedSchemaSection: azdata.GroupContainer;
|
private ownedSchemaSection: azdata.GroupContainer;
|
||||||
private membershipSection: azdata.GroupContainer;
|
private membershipSection: azdata.GroupContainer;
|
||||||
@@ -31,7 +32,7 @@ export class UserDialog extends ObjectManagementDialogBase<ObjectManagement.User
|
|||||||
private membershipTable: azdata.TableComponent;
|
private membershipTable: azdata.TableComponent;
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
super(objectManagementService, options);
|
super(objectManagementService, options, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override get helpUrl(): string {
|
protected override get helpUrl(): string {
|
||||||
@@ -61,12 +62,13 @@ export class UserDialog extends ObjectManagementDialogBase<ObjectManagement.User
|
|||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeUI(): Promise<void> {
|
protected override async initializeUI(): Promise<void> {
|
||||||
|
await super.initializeUI();
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
this.initializeOwnedSchemaSection();
|
this.initializeOwnedSchemaSection();
|
||||||
this.initializeMembershipSection();
|
this.initializeMembershipSection();
|
||||||
this.initializeAdvancedSection();
|
this.initializeAdvancedSection();
|
||||||
this.formContainer.addItems([this.generalSection, this.ownedSchemaSection, this.membershipSection, this.advancedSection]);
|
this.formContainer.addItems([this.generalSection, this.ownedSchemaSection, this.membershipSection, this.securableSection, this.advancedSection], this.getSectionItemLayout());
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setViewByUserType();
|
this.setViewByUserType();
|
||||||
}, 100);
|
}, 100);
|
||||||
@@ -94,7 +96,7 @@ export class UserDialog extends ObjectManagementDialogBase<ObjectManagement.User
|
|||||||
|
|
||||||
this.loginDropdown = this.createDropdown(localizedConstants.LoginText, async (newValue) => {
|
this.loginDropdown = this.createDropdown(localizedConstants.LoginText, async (newValue) => {
|
||||||
this.objectInfo.loginName = newValue;
|
this.objectInfo.loginName = newValue;
|
||||||
}, this.viewInfo.logins, this.objectInfo.loginName, this.options.isNewObject);
|
}, this.options.isNewObject ? this.viewInfo.logins : [this.objectInfo.loginName], this.objectInfo.loginName, this.options.isNewObject);
|
||||||
this.loginContainer = this.createLabelInputContainer(localizedConstants.LoginText, this.loginDropdown);
|
this.loginContainer = this.createLabelInputContainer(localizedConstants.LoginText, this.loginDropdown);
|
||||||
|
|
||||||
this.passwordInput = this.createPasswordInputBox(localizedConstants.PasswordText, async (newValue) => {
|
this.passwordInput = this.createPasswordInputBox(localizedConstants.PasswordText, async (newValue) => {
|
||||||
@@ -119,7 +121,7 @@ export class UserDialog extends ObjectManagementDialogBase<ObjectManagement.User
|
|||||||
[localizedConstants.SchemaText],
|
[localizedConstants.SchemaText],
|
||||||
this.viewInfo.schemas,
|
this.viewInfo.schemas,
|
||||||
this.objectInfo.ownedSchemas,
|
this.objectInfo.ownedSchemas,
|
||||||
DefaultMaxTableHeight,
|
DefaultMaxTableRowCount,
|
||||||
(item) => {
|
(item) => {
|
||||||
// It is not allowed to have unassigned schema.
|
// It is not allowed to have unassigned schema.
|
||||||
return this.objectInfo.ownedSchemas.indexOf(item) === -1;
|
return this.objectInfo.ownedSchemas.indexOf(item) === -1;
|
||||||
@@ -157,6 +159,11 @@ export class UserDialog extends ObjectManagementDialogBase<ObjectManagement.User
|
|||||||
this.addItem(this.generalSection, this.confirmPasswordContainer);
|
this.addItem(this.generalSection, this.confirmPasswordContainer);
|
||||||
this.addItem(this.formContainer, this.advancedSection);
|
this.addItem(this.formContainer, this.advancedSection);
|
||||||
break;
|
break;
|
||||||
|
case ObjectManagement.UserType.WindowsUser:
|
||||||
|
if (this.objectInfo.loginName) {
|
||||||
|
this.addItem(this.generalSection, this.loginContainer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ import * as uiLoc from '../ui/localizedConstants';
|
|||||||
export const DefaultLabelWidth = 150;
|
export const DefaultLabelWidth = 150;
|
||||||
export const DefaultInputWidth = 300;
|
export const DefaultInputWidth = 300;
|
||||||
export const DefaultTableWidth = DefaultInputWidth + DefaultLabelWidth;
|
export const DefaultTableWidth = DefaultInputWidth + DefaultLabelWidth;
|
||||||
export const DefaultMaxTableHeight = 400;
|
export const DefaultMaxTableRowCount = 10;
|
||||||
export const DefaultMinTableRowCount = 1;
|
export const DefaultMinTableRowCount = 1;
|
||||||
export const TableRowHeight = 25;
|
const TableRowHeight = 25;
|
||||||
export const TableColumnHeaderHeight = 30;
|
const TableColumnHeaderHeight = 30;
|
||||||
|
|
||||||
export function getTableHeight(rowCount: number, minRowCount: number = DefaultMinTableRowCount, maxHeight: number = DefaultMaxTableHeight): number {
|
export function getTableHeight(rowCount: number, minRowCount: number = DefaultMinTableRowCount, maxRowCount: number = DefaultMaxTableRowCount): number {
|
||||||
return Math.min(Math.max(rowCount, minRowCount) * TableRowHeight + TableColumnHeaderHeight, maxHeight);
|
return Math.min(Math.max(rowCount, minRowCount), maxRowCount) * TableRowHeight + TableColumnHeaderHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TableListItemEnabledStateGetter<T> = (item: T) => boolean;
|
export type TableListItemEnabledStateGetter<T> = (item: T) => boolean;
|
||||||
@@ -168,7 +168,7 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
columnNames: string[],
|
columnNames: string[],
|
||||||
allItems: T[],
|
allItems: T[],
|
||||||
selectedItems: T[],
|
selectedItems: T[],
|
||||||
maxHeight: number = DefaultMaxTableHeight,
|
maxRowCount: number = DefaultMaxTableRowCount,
|
||||||
enabledStateGetter: TableListItemEnabledStateGetter<T> = DefaultTableListItemEnabledStateGetter,
|
enabledStateGetter: TableListItemEnabledStateGetter<T> = DefaultTableListItemEnabledStateGetter,
|
||||||
rowValueGetter: TableListItemValueGetter<T> = DefaultTableListItemValueGetter,
|
rowValueGetter: TableListItemValueGetter<T> = DefaultTableListItemValueGetter,
|
||||||
itemComparer: TableListItemComparer<T> = DefaultTableListItemComparer): azdata.TableComponent {
|
itemComparer: TableListItemComparer<T> = DefaultTableListItemComparer): azdata.TableComponent {
|
||||||
@@ -179,7 +179,7 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
data: data,
|
data: data,
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
value: uiLoc.SelectedText,
|
value: uiLoc.SelectText,
|
||||||
type: azdata.ColumnType.checkBox,
|
type: azdata.ColumnType.checkBox,
|
||||||
options: { actionOnCheckbox: azdata.ActionOnCellCheckboxCheck.customAction }
|
options: { actionOnCheckbox: azdata.ActionOnCellCheckboxCheck.customAction }
|
||||||
}, ...columnNames.map(name => {
|
}, ...columnNames.map(name => {
|
||||||
@@ -187,7 +187,7 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
width: DefaultTableWidth,
|
width: DefaultTableWidth,
|
||||||
height: getTableHeight(data.length, DefaultMinTableRowCount, maxHeight)
|
height: getTableHeight(data.length, DefaultMinTableRowCount, maxRowCount)
|
||||||
}
|
}
|
||||||
).component();
|
).component();
|
||||||
this.disposables.push(table.onCellAction!((arg: azdata.ICheckboxCellActionEventArgs) => {
|
this.disposables.push(table.onCellAction!((arg: azdata.ICheckboxCellActionEventArgs) => {
|
||||||
@@ -203,9 +203,11 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setTableData(table: azdata.TableComponent, data: any[][], maxHeight: number = DefaultMaxTableHeight) {
|
protected async setTableData(table: azdata.TableComponent, data: any[][], maxRowCount: number = DefaultMaxTableRowCount) {
|
||||||
table.data = data;
|
await table.updateProperties({
|
||||||
table.height = getTableHeight(data.length, DefaultMinTableRowCount, maxHeight);
|
data: data,
|
||||||
|
height: getTableHeight(data.length, DefaultMinTableRowCount, maxRowCount)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getDataForTableList<T>(
|
protected getDataForTableList<T>(
|
||||||
@@ -221,14 +223,14 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected createTable(ariaLabel: string, columns: azdata.TableColumn[], data: any[][], maxHeight: number = DefaultMaxTableHeight): azdata.TableComponent {
|
protected createTable(ariaLabel: string, columns: string[], data: any[][], maxRowCount: number = DefaultMaxTableRowCount): azdata.TableComponent {
|
||||||
const table = this.modelView.modelBuilder.table().withProps(
|
const table = this.modelView.modelBuilder.table().withProps(
|
||||||
{
|
{
|
||||||
ariaLabel: ariaLabel,
|
ariaLabel: ariaLabel,
|
||||||
data: data,
|
data: data,
|
||||||
columns: columns,
|
columns: columns,
|
||||||
width: DefaultTableWidth,
|
width: DefaultTableWidth,
|
||||||
height: getTableHeight(data.length, DefaultMinTableRowCount, maxHeight)
|
height: getTableHeight(data.length, DefaultMinTableRowCount, maxRowCount)
|
||||||
}
|
}
|
||||||
).component();
|
).component();
|
||||||
return table;
|
return table;
|
||||||
@@ -238,7 +240,8 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
let addButton: azdata.ButtonComponent;
|
let addButton: azdata.ButtonComponent;
|
||||||
let removeButton: azdata.ButtonComponent;
|
let removeButton: azdata.ButtonComponent;
|
||||||
const updateButtons = () => {
|
const updateButtons = () => {
|
||||||
removeButton.enabled = table.selectedRows.length > 0;
|
this.onFormFieldChange();
|
||||||
|
removeButton.enabled = table.selectedRows?.length === 1 && table.selectedRows[0] !== -1 && table.selectedRows[0] < table.data.length;
|
||||||
}
|
}
|
||||||
addButton = this.createButton(uiLoc.AddText, addButtonAriaLabel, async () => {
|
addButton = this.createButton(uiLoc.AddText, addButtonAriaLabel, async () => {
|
||||||
await addHandler();
|
await addHandler();
|
||||||
@@ -246,6 +249,9 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
});
|
});
|
||||||
removeButton = this.createButton(uiLoc.RemoveText, removeButtonAriaLabel, async () => {
|
removeButton = this.createButton(uiLoc.RemoveText, removeButtonAriaLabel, async () => {
|
||||||
await removeHandler();
|
await removeHandler();
|
||||||
|
if (table.selectedRows.length === 1 && table.selectedRows[0] >= table.data.length) {
|
||||||
|
table.selectedRows = [table.data.length - 1];
|
||||||
|
}
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}, false);
|
}, false);
|
||||||
this.disposables.push(table.onRowSelected(() => {
|
this.disposables.push(table.onRowSelected(() => {
|
||||||
@@ -308,12 +314,12 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected addItem(container: azdata.DivContainer | azdata.FlexContainer, item: azdata.Component, index?: number): void {
|
protected addItem(container: azdata.DivContainer | azdata.FlexContainer, item: azdata.Component, itemLayout?: azdata.FlexItemLayout, index?: number): void {
|
||||||
if (container.items.indexOf(item) === -1) {
|
if (container.items.indexOf(item) === -1) {
|
||||||
if (index === undefined) {
|
if (index === undefined) {
|
||||||
container.addItem(item);
|
container.addItem(item, itemLayout);
|
||||||
} else {
|
} else {
|
||||||
container.insertItem(item, index);
|
container.insertItem(item, index, itemLayout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,6 +333,10 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
private createFormContainer(items: azdata.Component[]): azdata.DivContainer {
|
private createFormContainer(items: azdata.Component[]): azdata.DivContainer {
|
||||||
return this.modelView.modelBuilder.divContainer().withLayout({ width: 'calc(100% - 20px)', height: 'calc(100% - 20px)' }).withProps({
|
return this.modelView.modelBuilder.divContainer().withLayout({ width: 'calc(100% - 20px)', height: 'calc(100% - 20px)' }).withProps({
|
||||||
CSSStyles: { 'padding': '10px' }
|
CSSStyles: { 'padding': '10px' }
|
||||||
}).withItems(items, { CSSStyles: { 'margin-block-end': '10px' } }).component();
|
}).withItems(items, this.getSectionItemLayout()).component();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getSectionItemLayout(): azdata.FlexItemLayout {
|
||||||
|
return { CSSStyles: { 'margin-block-end': '5px' } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const YesText: string = localize('mssql.ui.yesText', "Yes");
|
|||||||
export const OkText: string = localize('mssql.ui.OkText', "OK");
|
export const OkText: string = localize('mssql.ui.OkText', "OK");
|
||||||
export const LoadingDialogText: string = localize('mssql.ui.loadingDialog', "Loading dialog...");
|
export const LoadingDialogText: string = localize('mssql.ui.loadingDialog', "Loading dialog...");
|
||||||
export const ScriptText: string = localize('mssql.ui.scriptText', "Script");
|
export const ScriptText: string = localize('mssql.ui.scriptText', "Script");
|
||||||
export const SelectedText = localize('objectManagement.selectedLabel', "Selected");
|
export const SelectText = localize('objectManagement.selectLabel', "Select");
|
||||||
export const AddText = localize('objectManagement.addText', "Add…");
|
export const AddText = localize('objectManagement.addText', "Add…");
|
||||||
export const RemoveText = localize('objectManagement.removeText', "Remove");
|
export const RemoveText = localize('objectManagement.removeText', "Remove");
|
||||||
export const NoActionScriptedMessage: string = localize('mssql.ui.noActionScriptedMessage', "There is no action to be scripted.");
|
export const NoActionScriptedMessage: string = localize('mssql.ui.noActionScriptedMessage', "There is no action to be scripted.");
|
||||||
|
|||||||
@@ -163,11 +163,6 @@
|
|||||||
"command": "jupyter.reinstallDependencies",
|
"command": "jupyter.reinstallDependencies",
|
||||||
"title": "%title.reinstallNotebookDependencies%"
|
"title": "%title.reinstallNotebookDependencies%"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "books.sqlserver2019",
|
|
||||||
"title": "%title.SQL19PreviewBook%",
|
|
||||||
"category": "%books-preview-category%"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "books.command.openLocalizedBooks",
|
"command": "books.command.openLocalizedBooks",
|
||||||
"title": "%title.PreviewLocalizedBook%",
|
"title": "%title.PreviewLocalizedBook%",
|
||||||
@@ -380,10 +375,6 @@
|
|||||||
"command": "jupyter.cmd.managePackages",
|
"command": "jupyter.cmd.managePackages",
|
||||||
"when": "false"
|
"when": "false"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "books.sqlserver2019",
|
|
||||||
"when": "sqlserver2019"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "notebook.command.saveBook",
|
"command": "notebook.command.saveBook",
|
||||||
"when": "false"
|
"when": "false"
|
||||||
@@ -542,10 +533,6 @@
|
|||||||
"when": "view == bookTreeView",
|
"when": "view == bookTreeView",
|
||||||
"group": "navigation"
|
"group": "navigation"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "books.sqlserver2019",
|
|
||||||
"when": "view == providedBooksView"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "notebook.command.openNotebookFolder",
|
"command": "notebook.command.openNotebookFolder",
|
||||||
"when": "view == bookTreeView",
|
"when": "view == bookTreeView",
|
||||||
|
|||||||
@@ -295,7 +295,8 @@ export function createViewContext(): ViewTestContext {
|
|||||||
columns: [] as string[],
|
columns: [] as string[],
|
||||||
onRowSelected: onClick.event,
|
onRowSelected: onClick.event,
|
||||||
onCellAction: onClick.event,
|
onCellAction: onClick.event,
|
||||||
appendData: (_data: any[][]) => undefined
|
appendData: (_data: any[][]) => undefined,
|
||||||
|
setActiveCell: (_row: number, _column: number) => undefined
|
||||||
});
|
});
|
||||||
let tableBuilder: azdata.ComponentBuilder<azdata.TableComponent, azdata.TableComponentProperties> = {
|
let tableBuilder: azdata.ComponentBuilder<azdata.TableComponent, azdata.TableComponentProperties> = {
|
||||||
component: () => table(),
|
component: () => table(),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "sql-database-projects",
|
"name": "sql-database-projects",
|
||||||
"displayName": "SQL Database Projects",
|
"displayName": "SQL Database Projects",
|
||||||
"description": "Enables users to develop and publish database schemas for MSSQL Databases",
|
"description": "Enables users to develop and publish database schemas for MSSQL Databases",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": false,
|
"preview": false,
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/t
|
|||||||
import { Deferred } from '../common/promise';
|
import { Deferred } from '../common/promise';
|
||||||
import { PublishOptionsDialog } from './publishOptionsDialog';
|
import { PublishOptionsDialog } from './publishOptionsDialog';
|
||||||
import { IPublishToDockerSettings, ISqlProjectPublishSettings } from '../models/deploy/publishSettings';
|
import { IPublishToDockerSettings, ISqlProjectPublishSettings } from '../models/deploy/publishSettings';
|
||||||
|
import { PublishProfile } from '../models/publishProfile/publishProfile';
|
||||||
|
|
||||||
interface DataSourceDropdownValue extends azdataType.CategoryValue {
|
interface DataSourceDropdownValue extends azdataType.CategoryValue {
|
||||||
dataSource: SqlConnectionDataSource;
|
dataSource: SqlConnectionDataSource;
|
||||||
@@ -69,7 +70,7 @@ export class PublishDatabaseDialog {
|
|||||||
public publish: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
|
public publish: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
|
||||||
public publishToContainer: ((proj: Project, profile: IPublishToDockerSettings) => any) | undefined;
|
public publishToContainer: ((proj: Project, profile: IPublishToDockerSettings) => any) | undefined;
|
||||||
public generateScript: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
|
public generateScript: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
|
||||||
public readPublishProfile: ((profileUri: vscode.Uri) => any) | undefined;
|
public readPublishProfile: ((profileUri: vscode.Uri) => Promise<PublishProfile>) | undefined;
|
||||||
public savePublishProfile: ((profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: DeploymentOptions) => any) | undefined;
|
public savePublishProfile: ((profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Map<string, string>, deploymentOptions?: DeploymentOptions) => any) | undefined;
|
||||||
|
|
||||||
constructor(private project: Project) {
|
constructor(private project: Project) {
|
||||||
@@ -814,8 +815,8 @@ export class PublishDatabaseDialog {
|
|||||||
this.formBuilder?.removeFormItem(<azdataType.FormComponentGroup>this.sqlCmdVariablesFormComponentGroup);
|
this.formBuilder?.removeFormItem(<azdataType.FormComponentGroup>this.sqlCmdVariablesFormComponentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let key in result.sqlCmdVariables) {
|
for (let key of result.sqlCmdVariables.keys()) {
|
||||||
this.sqlCmdVars?.set(key, result.sqlCmdVariableColumn.get(key));
|
this.sqlCmdVars?.set(key, result.sqlCmdVariables.get(key)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateRevertSqlCmdVarsButtonState();
|
this.updateRevertSqlCmdVarsButtonState();
|
||||||
@@ -983,7 +984,7 @@ export class PublishDatabaseDialog {
|
|||||||
/*
|
/*
|
||||||
* Sets the default deployment options to deployment options model object
|
* Sets the default deployment options to deployment options model object
|
||||||
*/
|
*/
|
||||||
public setDeploymentOptions(deploymentOptions: DeploymentOptions): void {
|
public setDeploymentOptions(deploymentOptions: DeploymentOptions | undefined): void {
|
||||||
this.deploymentOptions = deploymentOptions;
|
this.deploymentOptions = deploymentOptions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,9 +159,7 @@ export async function getPublishDatabaseSettings(project: ISqlProject, promptFor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. Modify sqlcmd vars
|
// 4. Modify sqlcmd vars
|
||||||
// If a publish profile is provided then the values from there will overwrite the ones in the
|
let sqlCmdVariables: Map<string, string> = getInitialSqlCmdVariables(project, publishProfile);
|
||||||
// project file (if they exist)
|
|
||||||
let sqlCmdVariables = Object.assign({}, project.sqlCmdVariables, publishProfile?.sqlCmdVariables);
|
|
||||||
|
|
||||||
if (sqlCmdVariables.size > 0) {
|
if (sqlCmdVariables.size > 0) {
|
||||||
// Continually loop here, allowing the user to modify SQLCMD variables one
|
// Continually loop here, allowing the user to modify SQLCMD variables one
|
||||||
@@ -170,13 +168,14 @@ export async function getPublishDatabaseSettings(project: ISqlProject, promptFor
|
|||||||
// as many times as they wish - with an option to reset all the variables
|
// as many times as they wish - with an option to reset all the variables
|
||||||
// to their starting values being provided as well.
|
// to their starting values being provided as well.
|
||||||
while (true) {
|
while (true) {
|
||||||
const quickPickItems = Object.keys(sqlCmdVariables).map(key => {
|
let quickPickItems = [];
|
||||||
return {
|
for (const key of sqlCmdVariables.keys()) {
|
||||||
|
quickPickItems.push({
|
||||||
label: key,
|
label: key,
|
||||||
description: sqlCmdVariables.get(key),
|
description: sqlCmdVariables.get(key),
|
||||||
key: key
|
key: key
|
||||||
} as vscode.QuickPickItem & { key?: string, isResetAllVars?: boolean, isDone?: boolean };
|
} as vscode.QuickPickItem & { key?: string, isResetAllVars?: boolean, isDone?: boolean })
|
||||||
});
|
}
|
||||||
quickPickItems.push({ label: `$(refresh) ${constants.resetAllVars}`, isResetAllVars: true });
|
quickPickItems.push({ label: `$(refresh) ${constants.resetAllVars}`, isResetAllVars: true });
|
||||||
quickPickItems.unshift({ label: `$(check) ${constants.done}`, isDone: true });
|
quickPickItems.unshift({ label: `$(check) ${constants.done}`, isDone: true });
|
||||||
const sqlCmd = await vscode.window.showQuickPick(
|
const sqlCmd = await vscode.window.showQuickPick(
|
||||||
@@ -200,7 +199,7 @@ export async function getPublishDatabaseSettings(project: ISqlProject, promptFor
|
|||||||
sqlCmdVariables.set(sqlCmd.key, newValue);
|
sqlCmdVariables.set(sqlCmd.key, newValue);
|
||||||
}
|
}
|
||||||
} else if (sqlCmd.isResetAllVars) {
|
} else if (sqlCmd.isResetAllVars) {
|
||||||
sqlCmdVariables = Object.assign({}, project.sqlCmdVariables, publishProfile?.sqlCmdVariables);
|
sqlCmdVariables = getInitialSqlCmdVariables(project, publishProfile);
|
||||||
} else if (sqlCmd.isDone) {
|
} else if (sqlCmd.isDone) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -220,6 +219,24 @@ export async function getPublishDatabaseSettings(project: ISqlProject, promptFor
|
|||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the sqlcmd variables from a sql projects. If a publish profile is provided then the values from there will overwrite the ones in the project file (if they exist)
|
||||||
|
* @param project
|
||||||
|
* @param publishProfile
|
||||||
|
* @returns Map of sqlcmd variables
|
||||||
|
*/
|
||||||
|
function getInitialSqlCmdVariables(project: ISqlProject, publishProfile?: PublishProfile): Map<string, string> {
|
||||||
|
// create a copy of the sqlcmd variable map so that the original ones don't get overwritten
|
||||||
|
let sqlCmdVariables = new Map(project.sqlCmdVariables);
|
||||||
|
if (publishProfile?.sqlCmdVariables) {
|
||||||
|
for (const [key, value] of publishProfile.sqlCmdVariables) {
|
||||||
|
sqlCmdVariables.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlCmdVariables;
|
||||||
|
}
|
||||||
|
|
||||||
export async function launchPublishTargetOption(project: Project): Promise<constants.PublishTargetType | undefined> {
|
export async function launchPublishTargetOption(project: Project): Promise<constants.PublishTargetType | undefined> {
|
||||||
// Show options to user for deploy to existing server or docker
|
// Show options to user for deploy to existing server or docker
|
||||||
const target = project.getProjectTargetVersion();
|
const target = project.getProjectTargetVersion();
|
||||||
|
|||||||
13
package.json
13
package.json
@@ -108,7 +108,7 @@
|
|||||||
"tas-client-umd": "0.1.6",
|
"tas-client-umd": "0.1.6",
|
||||||
"turndown": "^7.0.0",
|
"turndown": "^7.0.0",
|
||||||
"turndown-plugin-gfm": "^1.0.2",
|
"turndown-plugin-gfm": "^1.0.2",
|
||||||
"v8-inspect-profiler": "^0.0.22",
|
"v8-inspect-profiler": "^0.1.0",
|
||||||
"vscode-oniguruma": "1.6.1",
|
"vscode-oniguruma": "1.6.1",
|
||||||
"vscode-policy-watcher": "^1.1.1",
|
"vscode-policy-watcher": "^1.1.1",
|
||||||
"vscode-proxy-agent": "^0.12.0",
|
"vscode-proxy-agent": "^0.12.0",
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
"@types/node": "16.x",
|
"@types/node": "16.x",
|
||||||
"@types/plotly.js": "^1.44.9",
|
"@types/plotly.js": "^1.44.9",
|
||||||
"@types/sanitize-html": "^1.18.2",
|
"@types/sanitize-html": "^1.18.2",
|
||||||
"@types/sinon": "^10.0.2",
|
"@types/sinon": "10.0.2",
|
||||||
"@types/sinon-test": "^2.4.2",
|
"@types/sinon-test": "^2.4.2",
|
||||||
"@types/trusted-types": "^1.0.6",
|
"@types/trusted-types": "^1.0.6",
|
||||||
"@types/vscode-notebook-renderer": "1.60.0",
|
"@types/vscode-notebook-renderer": "1.60.0",
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
"gulp-bom": "^3.0.0",
|
"gulp-bom": "^3.0.0",
|
||||||
"gulp-buffer": "0.0.2",
|
"gulp-buffer": "0.0.2",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-eslint": "^6.0.0",
|
"gulp-eslint": "^5.0.0",
|
||||||
"gulp-filter": "^5.1.0",
|
"gulp-filter": "^5.1.0",
|
||||||
"gulp-flatmap": "^1.0.2",
|
"gulp-flatmap": "^1.0.2",
|
||||||
"gulp-gunzip": "^1.0.0",
|
"gulp-gunzip": "^1.0.0",
|
||||||
@@ -198,7 +198,6 @@
|
|||||||
"gulp-remote-retry-src": "^0.8.0",
|
"gulp-remote-retry-src": "^0.8.0",
|
||||||
"gulp-rename": "^1.2.0",
|
"gulp-rename": "^1.2.0",
|
||||||
"gulp-replace": "^0.5.4",
|
"gulp-replace": "^0.5.4",
|
||||||
"gulp-shell": "^0.6.5",
|
|
||||||
"gulp-sourcemaps": "^3.0.0",
|
"gulp-sourcemaps": "^3.0.0",
|
||||||
"gulp-svgmin": "^4.1.0",
|
"gulp-svgmin": "^4.1.0",
|
||||||
"gulp-untar": "^0.0.7",
|
"gulp-untar": "^0.0.7",
|
||||||
@@ -230,16 +229,16 @@
|
|||||||
"rcedit": "^1.1.0",
|
"rcedit": "^1.1.0",
|
||||||
"request": "^2.85.0",
|
"request": "^2.85.0",
|
||||||
"rimraf": "^2.2.8",
|
"rimraf": "^2.2.8",
|
||||||
"sinon": "^11.1.1",
|
"sinon": "11.1.1",
|
||||||
"sinon-test": "^3.1.3",
|
"sinon-test": "^3.1.3",
|
||||||
"source-map": "0.6.1",
|
"source-map": "0.6.1",
|
||||||
"source-map-support": "^0.3.2",
|
"source-map-support": "^0.3.2",
|
||||||
"style-loader": "^1.0.0",
|
"style-loader": "^1.3.0",
|
||||||
"temp-write": "^3.4.0",
|
"temp-write": "^3.4.0",
|
||||||
"ts-loader": "^9.2.7",
|
"ts-loader": "^9.2.7",
|
||||||
"tsec": "0.1.4",
|
"tsec": "0.1.4",
|
||||||
"typemoq": "^0.3.2",
|
"typemoq": "^0.3.2",
|
||||||
"typescript": "^4.8.0-dev.20220518",
|
"typescript": "4.8.0-dev.20220719",
|
||||||
"typescript-formatter": "7.1.0",
|
"typescript-formatter": "7.1.0",
|
||||||
"underscore": "^1.12.1",
|
"underscore": "^1.12.1",
|
||||||
"util": "^0.12.4",
|
"util": "^0.12.4",
|
||||||
|
|||||||
30
src/sql/azdata.proposed.d.ts
vendored
30
src/sql/azdata.proposed.d.ts
vendored
@@ -1797,6 +1797,10 @@ declare module 'azdata' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeFilterProperty {
|
export interface NodeFilterProperty {
|
||||||
|
/**
|
||||||
|
* The non-localized name of the filter property
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
/**
|
/**
|
||||||
* The name of the filter property displayed to the user
|
* The name of the filter property displayed to the user
|
||||||
*/
|
*/
|
||||||
@@ -1818,14 +1822,27 @@ declare module 'azdata' {
|
|||||||
/**
|
/**
|
||||||
* The list of choices for the filter property if the type is choice
|
* The list of choices for the filter property if the type is choice
|
||||||
*/
|
*/
|
||||||
choices: string[];
|
choices: NodeFilterChoicePropertyValue[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeFilterChoicePropertyValue {
|
||||||
|
/**
|
||||||
|
* The value of the choice
|
||||||
|
*/
|
||||||
|
value: string;
|
||||||
|
/**
|
||||||
|
* The display name of the choice
|
||||||
|
* If not specified, the value will be used as the display name
|
||||||
|
* If specified, the display name will be used in the dropdown
|
||||||
|
*/
|
||||||
|
displayName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeFilter {
|
export interface NodeFilter {
|
||||||
/**
|
/**
|
||||||
* The name of the filter property
|
* The name of the filter property
|
||||||
*/
|
*/
|
||||||
name: string;
|
displayName: string;
|
||||||
/**
|
/**
|
||||||
* The operator of the filter property
|
* The operator of the filter property
|
||||||
*/
|
*/
|
||||||
@@ -1833,7 +1850,7 @@ declare module 'azdata' {
|
|||||||
/**
|
/**
|
||||||
* The applied values of the filter property
|
* The applied values of the filter property
|
||||||
*/
|
*/
|
||||||
value: string | string[] | number | boolean | undefined;
|
value: string | string[] | number | number[] | boolean | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NodeFilterPropertyDataType {
|
export enum NodeFilterPropertyDataType {
|
||||||
@@ -1930,4 +1947,11 @@ declare module 'azdata' {
|
|||||||
isPrimary: boolean;
|
isPrimary: boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TableComponent {
|
||||||
|
/**
|
||||||
|
* Set active cell.
|
||||||
|
*/
|
||||||
|
setActiveCell(row: number, column: number): void;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export class TableCellEditorFactory {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTextEditorClass(context: any, inputType: 'text' | 'number' = 'text'): any {
|
public getTextEditorClass(context: any, inputType: 'text' | 'number' | 'date' = 'text', presetValue?: string): any {
|
||||||
const self = this;
|
const self = this;
|
||||||
class TextEditor extends Disposable {
|
class TextEditor extends Disposable {
|
||||||
private _originalValue: string;
|
private _originalValue: string;
|
||||||
@@ -76,6 +76,8 @@ export class TableCellEditorFactory {
|
|||||||
this._register(self._options.onStyleChange(() => {
|
this._register(self._options.onStyleChange(() => {
|
||||||
self._options.editorStyler(this._input);
|
self._options.editorStyler(this._input);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this._input.value = presetValue ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
private async commitEdit(): Promise<void> {
|
private async commitEdit(): Promise<void> {
|
||||||
@@ -96,11 +98,21 @@ export class TableCellEditorFactory {
|
|||||||
|
|
||||||
public loadValue(item: Slick.SlickData): void {
|
public loadValue(item: Slick.SlickData): void {
|
||||||
this._originalValue = self._options.valueGetter(item, this._args.column) ?? '';
|
this._originalValue = self._options.valueGetter(item, this._args.column) ?? '';
|
||||||
this._input.value = this._originalValue;
|
if (inputType === 'date') {
|
||||||
|
this._input.inputElement.valueAsDate = new Date(this._originalValue);
|
||||||
|
} else {
|
||||||
|
this._input.value = this._originalValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public applyValue(item: Slick.SlickData, state: string): void {
|
public applyValue(item: Slick.SlickData, state: string): void {
|
||||||
const activeCell = this._args.grid.getActiveCell();
|
const activeCell = this._args.grid.getActiveCell();
|
||||||
|
if (inputType === 'date') {
|
||||||
|
// Usually, the date picker will return the date in the local time zone and change the date to the previous day.
|
||||||
|
// We need to convert the date to UTC time zone to avoid this behavior so that the date will be the same as the
|
||||||
|
// date picked in the date picker.
|
||||||
|
state = new Date(state).toLocaleDateString(window.navigator.language, { timeZone: 'UTC' });
|
||||||
|
}
|
||||||
self._options.valueSetter(context, activeCell.row, item, this._args.column, state);
|
self._options.valueSetter(context, activeCell.row, item, this._args.column, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,10 +97,24 @@ export class TestCapabilitiesService implements ICapabilitiesService {
|
|||||||
valueType: ServiceOptionType.string
|
valueType: ServiceOptionType.string
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
let mssqlAdvancedOptions: azdata.ConnectionOption[] = [
|
||||||
|
{
|
||||||
|
name: 'trustServerCertificate',
|
||||||
|
displayName: undefined!,
|
||||||
|
description: undefined!,
|
||||||
|
groupName: undefined!,
|
||||||
|
categoryValues: undefined!,
|
||||||
|
defaultValue: 'false',
|
||||||
|
isIdentity: false,
|
||||||
|
isRequired: false,
|
||||||
|
specialValueType: undefined!,
|
||||||
|
valueType: ServiceOptionType.boolean
|
||||||
|
}
|
||||||
|
];
|
||||||
let msSQLCapabilities = {
|
let msSQLCapabilities = {
|
||||||
providerId: mssqlProviderName,
|
providerId: mssqlProviderName,
|
||||||
displayName: 'MSSQL',
|
displayName: 'MSSQL',
|
||||||
connectionOptions: connectionProvider,
|
connectionOptions: connectionProvider.concat(mssqlAdvancedOptions),
|
||||||
};
|
};
|
||||||
let pgSQLCapabilities = {
|
let pgSQLCapabilities = {
|
||||||
providerId: this.pgsqlProviderName,
|
providerId: this.pgsqlProviderName,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ConnectionConfig } from 'sql/platform/connection/common/connectionConfi
|
|||||||
import { fixupConnectionCredentials } from 'sql/platform/connection/common/connectionInfo';
|
import { fixupConnectionCredentials } from 'sql/platform/connection/common/connectionInfo';
|
||||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||||
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
|
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
|
||||||
import { AuthenticationType } from 'sql/platform/connection/common/constants';
|
import { AuthenticationType, mssqlProviderName } from 'sql/platform/connection/common/constants';
|
||||||
import { IConnectionProfile, ProfileMatcher } from 'sql/platform/connection/common/interfaces';
|
import { IConnectionProfile, ProfileMatcher } from 'sql/platform/connection/common/interfaces';
|
||||||
import { ICredentialsService } from 'sql/platform/credentials/common/credentialsService';
|
import { ICredentialsService } from 'sql/platform/credentials/common/credentialsService';
|
||||||
import { isDisposable } from 'vs/base/common/lifecycle';
|
import { isDisposable } from 'vs/base/common/lifecycle';
|
||||||
@@ -84,10 +84,28 @@ export class ConnectionStore {
|
|||||||
if (credentialsItem.savePassword && this.isPasswordRequired(credentialsItem) && !credentialsItem.password) {
|
if (credentialsItem.savePassword && this.isPasswordRequired(credentialsItem) && !credentialsItem.password) {
|
||||||
const credentialId = this.formatCredentialId(credentialsItem, CRED_PROFILE_USER);
|
const credentialId = this.formatCredentialId(credentialsItem, CRED_PROFILE_USER);
|
||||||
return this.credentialService.readCredential(credentialId)
|
return this.credentialService.readCredential(credentialId)
|
||||||
.then(savedCred => {
|
.then(async savedCred => {
|
||||||
if (savedCred) {
|
if (savedCred?.password) {
|
||||||
credentialsItem.password = savedCred.password;
|
credentialsItem.password = savedCred.password;
|
||||||
credentialsItem.options['password'] = savedCred.password;
|
credentialsItem.options['password'] = savedCred.password;
|
||||||
|
} else if (credentialsItem.providerName === mssqlProviderName) {
|
||||||
|
// Special handling for MSSQL provider as "applicationName:azdata" is no longer included
|
||||||
|
// in credential string starting with MAY 2023 release.
|
||||||
|
// We will try to read credential including applicationName and if it is found,
|
||||||
|
// we will update the saved credential with new credential key.
|
||||||
|
// This special case handling should be removed in a future release.
|
||||||
|
let credParts = credentialId.split('|');
|
||||||
|
credParts.splice(3, 0, 'applicationName:azdata');
|
||||||
|
const oldCredentialId = credParts.join('|');
|
||||||
|
const savedMssqlCred = await this.credentialService.readCredential(oldCredentialId);
|
||||||
|
if (savedMssqlCred?.password) {
|
||||||
|
credentialsItem.password = savedMssqlCred.password;
|
||||||
|
credentialsItem.options['password'] = savedMssqlCred.password;
|
||||||
|
// Update credential in credential store.
|
||||||
|
await this.credentialService.deleteCredential(oldCredentialId);
|
||||||
|
await this.credentialService.saveCredential(credentialId, savedMssqlCred.password);
|
||||||
|
savedCred.password = savedMssqlCred.password;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return { profile: credentialsItem, savedCred: !!savedCred };
|
return { profile: credentialsItem, savedCred: !!savedCred };
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -202,6 +202,27 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo {
|
|||||||
* Example: "providerName:MSSQL|authenticationType:|databaseName:database|serverName:server3|userName:user|group:testid"
|
* Example: "providerName:MSSQL|authenticationType:|databaseName:database|serverName:server3|userName:user|group:testid"
|
||||||
*/
|
*/
|
||||||
public getOptionsKey(): string {
|
public getOptionsKey(): string {
|
||||||
|
let idNames = this.getOptionKeyIdNames();
|
||||||
|
idNames = idNames.filter(x => x !== undefined);
|
||||||
|
|
||||||
|
//Sort to make sure using names in the same order every time otherwise the ids would be different
|
||||||
|
idNames.sort();
|
||||||
|
|
||||||
|
let idValues: string[] = [];
|
||||||
|
for (let index = 0; index < idNames.length; index++) {
|
||||||
|
let value = this.options[idNames[index]!];
|
||||||
|
value = value ? value : '';
|
||||||
|
idValues.push(`${idNames[index]}${ProviderConnectionInfo.nameValueSeparator}${value}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProviderConnectionInfo.ProviderPropertyName + ProviderConnectionInfo.nameValueSeparator +
|
||||||
|
this.providerName + ProviderConnectionInfo.idSeparator + idValues.join(ProviderConnectionInfo.idSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns Array of option key names
|
||||||
|
*/
|
||||||
|
public getOptionKeyIdNames(): string[] {
|
||||||
let idNames = [];
|
let idNames = [];
|
||||||
if (this.serverCapabilities) {
|
if (this.serverCapabilities) {
|
||||||
idNames = this.serverCapabilities.connectionOptions.map(o => {
|
idNames = this.serverCapabilities.connectionOptions.map(o => {
|
||||||
@@ -217,21 +238,7 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo {
|
|||||||
// This should never happen but just incase the serverCapabilities was not ready at this time
|
// This should never happen but just incase the serverCapabilities was not ready at this time
|
||||||
idNames = ['authenticationType', 'database', 'server', 'user'];
|
idNames = ['authenticationType', 'database', 'server', 'user'];
|
||||||
}
|
}
|
||||||
|
return idNames;
|
||||||
idNames = idNames.filter(x => x !== undefined);
|
|
||||||
|
|
||||||
//Sort to make sure using names in the same order every time otherwise the ids would be different
|
|
||||||
idNames.sort();
|
|
||||||
|
|
||||||
let idValues: string[] = [];
|
|
||||||
for (let index = 0; index < idNames.length; index++) {
|
|
||||||
let value = this.options[idNames[index]!];
|
|
||||||
value = value ? value : '';
|
|
||||||
idValues.push(`${idNames[index]}${ProviderConnectionInfo.nameValueSeparator}${value}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ProviderConnectionInfo.ProviderPropertyName + ProviderConnectionInfo.nameValueSeparator +
|
|
||||||
this.providerName + ProviderConnectionInfo.idSeparator + idValues.join(ProviderConnectionInfo.idSeparator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getProviderFromOptionsKey(optionsKey: string) {
|
public static getProviderFromOptionsKey(optionsKey: string) {
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ export enum ComponentEventType {
|
|||||||
export enum ModelViewAction {
|
export enum ModelViewAction {
|
||||||
SelectTab = 'selectTab',
|
SelectTab = 'selectTab',
|
||||||
AppendData = 'appendData',
|
AppendData = 'appendData',
|
||||||
Filter = 'filter'
|
Filter = 'filter',
|
||||||
|
SetActiveCell = 'setActiveCell'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export const enum TelemetryView {
|
|||||||
ResultsPanel = 'ResultsPanel',
|
ResultsPanel = 'ResultsPanel',
|
||||||
Shell = 'Shell',
|
Shell = 'Shell',
|
||||||
SqlAssessment = 'SqlAssessment',
|
SqlAssessment = 'SqlAssessment',
|
||||||
TableDesigner = 'TableDesigner'
|
TableDesigner = 'TableDesigner',
|
||||||
|
ObjectExplorer = 'ObjectExplorer'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum TelemetryError {
|
export const enum TelemetryError {
|
||||||
@@ -98,6 +99,8 @@ export const enum TelemetryAction {
|
|||||||
MoveServerGroup = 'MoveServerGroup',
|
MoveServerGroup = 'MoveServerGroup',
|
||||||
NewQuery = 'NewQuery',
|
NewQuery = 'NewQuery',
|
||||||
ObjectExplorerExpand = 'ObjectExplorerExpand',
|
ObjectExplorerExpand = 'ObjectExplorerExpand',
|
||||||
|
ObjectExplorerFilter = 'ObjectExplorerFilter',
|
||||||
|
ObjectExplorerRemoveFilter = 'ObjectExplorerRemoveFilter',
|
||||||
Open = 'Open',
|
Open = 'Open',
|
||||||
OpenQuery = 'OpenQuery',
|
OpenQuery = 'OpenQuery',
|
||||||
OpenExecutionPlanProperties = 'OpenExecutionPlanProperties',
|
OpenExecutionPlanProperties = 'OpenExecutionPlanProperties',
|
||||||
|
|||||||
@@ -1503,6 +1503,10 @@ class TableComponentWrapper extends ComponentWrapper implements azdata.TableComp
|
|||||||
public appendData(v: any[][]): Thenable<void> {
|
public appendData(v: any[][]): Thenable<void> {
|
||||||
return this.doAction(ModelViewAction.AppendData, v);
|
return this.doAction(ModelViewAction.AppendData, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setActiveCell(row: number, column: number): void {
|
||||||
|
this.doAction(ModelViewAction.SetActiveCell, row, column);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DropDownWrapper extends ComponentWrapper implements azdata.DropDownComponent {
|
class DropDownWrapper extends ComponentWrapper implements azdata.DropDownComponent {
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ export enum ModelComponentTypes {
|
|||||||
export enum ModelViewAction {
|
export enum ModelViewAction {
|
||||||
SelectTab = 'selectTab',
|
SelectTab = 'selectTab',
|
||||||
AppendData = 'appendData',
|
AppendData = 'appendData',
|
||||||
Filter = 'filter'
|
Filter = 'filter',
|
||||||
|
SetActiveCell = 'setActiveCell'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ColumnSizingMode {
|
export enum ColumnSizingMode {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||||
import { ITableService } from 'sql/workbench/services/table/browser/tableService';
|
import { ITableService } from 'sql/workbench/services/table/browser/tableService';
|
||||||
|
import { deepClone, equals } from 'vs/base/common/objects';
|
||||||
|
|
||||||
export enum ColumnSizingMode {
|
export enum ColumnSizingMode {
|
||||||
ForceFit = 0, // all columns will be sized to fit in viewable space, no horiz scroll bar
|
ForceFit = 0, // all columns will be sized to fit in viewable space, no horiz scroll bar
|
||||||
@@ -358,24 +359,27 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override setProperties(properties: { [key: string]: any; }): void {
|
public override setProperties(properties: { [key: string]: any; }): void {
|
||||||
|
const oldColumns = deepClone(this.columns);
|
||||||
super.setProperties(properties);
|
super.setProperties(properties);
|
||||||
this._tableData.clear();
|
this._tableData.clear();
|
||||||
this._tableData.push(this.transformData(this.data, this.columns));
|
this._tableData.push(this.transformData(this.data, this.columns));
|
||||||
this._tableColumns = this.transformColumns(this.columns);
|
if (!equals(oldColumns, this.columns)) {
|
||||||
this._table.columns = this._tableColumns;
|
this._tableColumns = this.transformColumns(this.columns);
|
||||||
|
this._table.columns = this._tableColumns;
|
||||||
|
this._checkboxColumns.forEach((column, columnName) => { this.registerPlugins(columnName, column); })
|
||||||
|
Object.keys(this._buttonColumns).forEach(col => this.registerPlugins(col, this._buttonColumns[col]));
|
||||||
|
Object.keys(this._hyperlinkColumns).forEach(col => this.registerPlugins(col, this._hyperlinkColumns[col]));
|
||||||
|
Object.keys(this._contextMenuColumns).forEach(col => this.registerPlugins(col, this._contextMenuColumns[col]));
|
||||||
|
|
||||||
|
this._table.columns = this._tableColumns;
|
||||||
|
this._table.autosizeColumns();
|
||||||
|
}
|
||||||
this._table.setData(this._tableData);
|
this._table.setData(this._tableData);
|
||||||
this._table.setTableTitle(this.title);
|
this._table.setTableTitle(this.title);
|
||||||
if (this.selectedRows) {
|
if (this.selectedRows) {
|
||||||
this._table.setSelectedRows(this.selectedRows);
|
this._table.setSelectedRows(this.selectedRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._checkboxColumns.forEach((column, columnName) => {
|
|
||||||
this.registerPlugins(columnName, column);
|
|
||||||
})
|
|
||||||
Object.keys(this._buttonColumns).forEach(col => this.registerPlugins(col, this._buttonColumns[col]));
|
|
||||||
Object.keys(this._hyperlinkColumns).forEach(col => this.registerPlugins(col, this._hyperlinkColumns[col]));
|
|
||||||
Object.keys(this._contextMenuColumns).forEach(col => this.registerPlugins(col, this._contextMenuColumns[col]));
|
|
||||||
|
|
||||||
if (this.headerFilter === true) {
|
if (this.headerFilter === true) {
|
||||||
this.registerFilterPlugin();
|
this.registerFilterPlugin();
|
||||||
this._tableData.clearFilter();
|
this._tableData.clearFilter();
|
||||||
@@ -433,7 +437,8 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
width: col.width,
|
width: col.width,
|
||||||
cssClass: col.cssClass,
|
cssClass: col.cssClass,
|
||||||
headerCssClass: col.headerCssClass,
|
headerCssClass: col.headerCssClass,
|
||||||
actionOnCheck: checkboxAction
|
actionOnCheck: checkboxAction,
|
||||||
|
columnId: `checkbox-column-${index}`,
|
||||||
}, index));
|
}, index));
|
||||||
|
|
||||||
this._register(this._checkboxColumns.get(col.value).onChange((state) => {
|
this._register(this._checkboxColumns.get(col.value).onChange((state) => {
|
||||||
@@ -589,7 +594,6 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
|
|
||||||
|
|
||||||
private registerPlugins(col: string, plugin: CheckboxSelectColumn<{}> | ButtonColumn<{}> | HyperlinkColumn<{}> | ContextMenuColumn<{}>): void {
|
private registerPlugins(col: string, plugin: CheckboxSelectColumn<{}> | ButtonColumn<{}> | HyperlinkColumn<{}> | ContextMenuColumn<{}>): void {
|
||||||
|
|
||||||
const index = 'index' in plugin ? plugin.index : this.columns?.findIndex(x => x === col || ('value' in x && x['value'] === col));
|
const index = 'index' in plugin ? plugin.index : this.columns?.findIndex(x => x === col || ('value' in x && x['value'] === col));
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
this._tableColumns.splice(index, 0, plugin.definition);
|
this._tableColumns.splice(index, 0, plugin.definition);
|
||||||
@@ -598,10 +602,6 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
this._pluginsRegisterStatus[col] = true;
|
this._pluginsRegisterStatus[col] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._table.columns = this._tableColumns;
|
|
||||||
this._table.autosizeColumns();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -723,6 +723,10 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case ModelViewAction.AppendData:
|
case ModelViewAction.AppendData:
|
||||||
this.appendData(args[0]);
|
this.appendData(args[0]);
|
||||||
|
break;
|
||||||
|
case ModelViewAction.SetActiveCell:
|
||||||
|
this._table.grid.setActiveCell(args[0], args[1]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,17 +31,61 @@ import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/envi
|
|||||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||||
|
|
||||||
export interface SqlArgs {
|
export interface SqlArgs {
|
||||||
|
/**
|
||||||
|
* Used to determine file paths to be opened with SQL Editor.
|
||||||
|
* If provided, we connect the given profile to to it.
|
||||||
|
* More than one files can be passed to connect to provided profile.
|
||||||
|
*/
|
||||||
_?: string[];
|
_?: string[];
|
||||||
|
/**
|
||||||
|
* Provide authenticationType to be used.
|
||||||
|
* accepted values: AzureMFA, SqlLogin, Integrated, etc.
|
||||||
|
*/
|
||||||
authenticationType?: string
|
authenticationType?: string
|
||||||
|
/**
|
||||||
|
* Name of database
|
||||||
|
*/
|
||||||
database?: string;
|
database?: string;
|
||||||
|
/**
|
||||||
|
* Name of server
|
||||||
|
*/
|
||||||
server?: string;
|
server?: string;
|
||||||
|
/**
|
||||||
|
* User name/email address
|
||||||
|
*/
|
||||||
user?: string;
|
user?: string;
|
||||||
|
/**
|
||||||
|
* Operation to perform:
|
||||||
|
* accepted values: connect, openConnectionDialog
|
||||||
|
*/
|
||||||
command?: string;
|
command?: string;
|
||||||
|
/**
|
||||||
|
* Name of connection provider,
|
||||||
|
* accepted values: mssql (by default), pgsql, etc.
|
||||||
|
*/
|
||||||
provider?: string;
|
provider?: string;
|
||||||
aad?: boolean; // deprecated - used by SSMS - authenticationType should be used instead
|
/**
|
||||||
integrated?: boolean; // deprecated - used by SSMS - authenticationType should be used instead.
|
* Deprecated - used by SSMS - authenticationType should be used instead
|
||||||
|
*/
|
||||||
|
aad?: boolean;
|
||||||
|
/**
|
||||||
|
* Deprecated - used by SSMS - authenticationType should be used instead.
|
||||||
|
*/
|
||||||
|
integrated?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether or not to show dashboard
|
||||||
|
* accepted values: true, false (by default).
|
||||||
|
*/
|
||||||
showDashboard?: boolean;
|
showDashboard?: boolean;
|
||||||
|
/**
|
||||||
|
* Supports providing applicationName that will be used for connection profile app name.
|
||||||
|
*/
|
||||||
applicationName?: string;
|
applicationName?: string;
|
||||||
|
/**
|
||||||
|
* Supports providing advanced connection properties that providers support.
|
||||||
|
* Value must be a json object containing key-value pairs in format: '{"key1":"value1","key2":"value2",...}'
|
||||||
|
*/
|
||||||
|
connectionProperties?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region decorators
|
//#region decorators
|
||||||
@@ -324,9 +368,33 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
|
|||||||
profile.setOptionValue('applicationName', applicationName);
|
profile.setOptionValue('applicationName', applicationName);
|
||||||
profile.setOptionValue('databaseDisplayName', profile.databaseName);
|
profile.setOptionValue('databaseDisplayName', profile.databaseName);
|
||||||
profile.setOptionValue('groupId', profile.groupId);
|
profile.setOptionValue('groupId', profile.groupId);
|
||||||
|
// Set all advanced options
|
||||||
|
let advancedOptions = this.getAdvancedOptions(args.connectionProperties, profile.getOptionKeyIdNames());
|
||||||
|
advancedOptions.forEach((v, k) => {
|
||||||
|
profile.setOptionValue(k, v);
|
||||||
|
});
|
||||||
return this._connectionManagementService ? this.tryMatchSavedProfile(profile) : profile;
|
return this._connectionManagementService ? this.tryMatchSavedProfile(profile) : profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getAdvancedOptions(options: string, idNames: string[]): Map<string, string> {
|
||||||
|
const ignoredProperties = idNames.concat(['password', 'azureAccountToken']);
|
||||||
|
let advancedOptionsMap = new Map<string, string>();
|
||||||
|
if (options) {
|
||||||
|
try {
|
||||||
|
// Decode options if they contain any encoded URL characters
|
||||||
|
options = decodeURI(options);
|
||||||
|
JSON.parse(options, (k, v) => {
|
||||||
|
if (!(k in ignoredProperties)) {
|
||||||
|
advancedOptionsMap.set(k, v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(localize('commandline.propertiesFormatError', 'Advanced connection properties could not be parsed as JSON, error occurred: {0} Received properties value: {1}', e, options));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return advancedOptionsMap;
|
||||||
|
}
|
||||||
|
|
||||||
private tryMatchSavedProfile(profile: ConnectionProfile) {
|
private tryMatchSavedProfile(profile: ConnectionProfile) {
|
||||||
let match: ConnectionProfile = undefined;
|
let match: ConnectionProfile = undefined;
|
||||||
// If we can find a saved mssql provider connection that matches the args, use it
|
// If we can find a saved mssql provider connection that matches the args, use it
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ class TestParsedArgs implements NativeParsedArgs, SqlArgs {
|
|||||||
waitMarkerFilePath?: string;
|
waitMarkerFilePath?: string;
|
||||||
authenticationType?: string;
|
authenticationType?: string;
|
||||||
applicationName?: string;
|
applicationName?: string;
|
||||||
|
connectionProperties?: string;
|
||||||
}
|
}
|
||||||
suite('commandLineService tests', () => {
|
suite('commandLineService tests', () => {
|
||||||
|
|
||||||
@@ -219,6 +220,42 @@ suite('commandLineService tests', () => {
|
|||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processCommandLine loads advanced options in args', async () => {
|
||||||
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
const args: TestParsedArgs = new TestParsedArgs();
|
||||||
|
args.server = 'myserver';
|
||||||
|
args.database = 'mydatabase';
|
||||||
|
args.user = 'myuser';
|
||||||
|
args.authenticationType = Constants.AuthenticationType.SqlLogin;
|
||||||
|
args.applicationName = 'myapplication';
|
||||||
|
// Pass advanced connection properties
|
||||||
|
args.connectionProperties = `{"trustServerCertificate":"true"}`;
|
||||||
|
|
||||||
|
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
|
||||||
|
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
|
||||||
|
connectionManagementService.setup(c => c.getConnectionGroups(TypeMoq.It.isAny())).returns(() => []);
|
||||||
|
let originalProfile: IConnectionProfile = undefined;
|
||||||
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.is<ConnectionProfile>(
|
||||||
|
p => p.serverName === 'myserver'
|
||||||
|
&& p.authenticationType === Constants.AuthenticationType.SqlLogin
|
||||||
|
&& p.options['applicationName'] === 'myapplication-azdata'), 'connection', true))
|
||||||
|
.returns((conn) => {
|
||||||
|
originalProfile = conn;
|
||||||
|
return Promise.resolve('unused');
|
||||||
|
})
|
||||||
|
.verifiable(TypeMoq.Times.once());
|
||||||
|
connectionManagementService.setup(c => c.getConnectionProfileById(TypeMoq.It.isAnyString())).returns(() => originalProfile);
|
||||||
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
const logService = new NullLogService();
|
||||||
|
let contribution = getCommandLineContribution(connectionManagementService.object, configurationService.object, capabilitiesService, undefined, undefined, logService);
|
||||||
|
await contribution.processCommandLine(args);
|
||||||
|
assert.equal(originalProfile.options['applicationName'], 'myapplication-azdata', 'Application Name not received as expected.');
|
||||||
|
assert.equal(originalProfile.options['trustServerCertificate'], 'true', 'Advanced option not received as expected.');
|
||||||
|
connectionManagementService.verifyAll();
|
||||||
|
});
|
||||||
|
|
||||||
test('processCommandLine invokes a command without a profile parameter when no server is passed', async () => {
|
test('processCommandLine invokes a command without a profile parameter when no server is passed', async () => {
|
||||||
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Loose);
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Loose);
|
||||||
@@ -568,7 +605,5 @@ suite('commandLineService tests', () => {
|
|||||||
notificationService.verifyAll();
|
notificationService.verifyAll();
|
||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export class LinkHandlerDirective {
|
|||||||
@Inject(INotebookService) private readonly notebookService: INotebookService,
|
@Inject(INotebookService) private readonly notebookService: INotebookService,
|
||||||
@Inject(IFileService) private readonly fileService: IFileService
|
@Inject(IFileService) private readonly fileService: IFileService
|
||||||
) {
|
) {
|
||||||
this.workbenchFilePath = URI.parse(require.toUrl('vs/code/electron-browser/workbench/workbench.html'));
|
this.workbenchFilePath = URI.parse(require.toUrl('vs/code/electron-sandbox/workbench/workbench.html'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('click', ['$event'])
|
@HostListener('click', ['$event'])
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ import { ActionRunner } from 'vs/base/common/actions';
|
|||||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||||
import { USE_ASYNC_SERVER_TREE_CONFIG } from 'sql/workbench/contrib/objectExplorer/common/serverGroup.contribution';
|
import { USE_ASYNC_SERVER_TREE_CONFIG } from 'sql/workbench/contrib/objectExplorer/common/serverGroup.contribution';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
import { FilterDialog } from 'sql/workbench/services/objectExplorer/browser/filterDialog/filterDialog';
|
||||||
|
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
||||||
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
|
|
||||||
export const CONTEXT_SERVER_TREE_VIEW = new RawContextKey<ServerTreeViewView>('serverTreeView.view', ServerTreeViewView.all);
|
export const CONTEXT_SERVER_TREE_VIEW = new RawContextKey<ServerTreeViewView>('serverTreeView.view', ServerTreeViewView.all);
|
||||||
export const CONTEXT_SERVER_TREE_HAS_CONNECTIONS = new RawContextKey<boolean>('serverTreeView.hasConnections', false);
|
export const CONTEXT_SERVER_TREE_HAS_CONNECTIONS = new RawContextKey<boolean>('serverTreeView.hasConnections', false);
|
||||||
@@ -78,7 +81,8 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
|||||||
@IKeybindingService private _keybindingService: IKeybindingService,
|
@IKeybindingService private _keybindingService: IKeybindingService,
|
||||||
@IContextKeyService contextKeyService: IContextKeyService,
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
@IHostService private _hostService: IHostService,
|
@IHostService private _hostService: IHostService,
|
||||||
@INotificationService private _notificationService: INotificationService
|
@INotificationService private _notificationService: INotificationService,
|
||||||
|
@IAdsTelemetryService private _telemetryService: IAdsTelemetryService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._hasConnectionsKey = CONTEXT_SERVER_TREE_HAS_CONNECTIONS.bindTo(contextKeyService);
|
this._hasConnectionsKey = CONTEXT_SERVER_TREE_HAS_CONNECTIONS.bindTo(contextKeyService);
|
||||||
@@ -588,6 +592,50 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async filterElementChildren(node: TreeNode): Promise<void> {
|
||||||
|
await FilterDialog.getFiltersForProperties(
|
||||||
|
node.filterProperties,
|
||||||
|
localize('objectExplorer.filterDialogTitle', "(Preview) Filter Settings: {0}", node.getConnectionProfile().title),
|
||||||
|
localize('objectExplorer.nodePath', "Node Path: {0}", node.nodePath),
|
||||||
|
node.filters,
|
||||||
|
async (filters) => {
|
||||||
|
let errorListener;
|
||||||
|
try {
|
||||||
|
let expansionError = undefined;
|
||||||
|
errorListener = this._objectExplorerService.onUpdateObjectExplorerNodes(e => {
|
||||||
|
if (e.errorMessage) {
|
||||||
|
expansionError = e.errorMessage;
|
||||||
|
}
|
||||||
|
errorListener.dispose();
|
||||||
|
});
|
||||||
|
node.forceRefresh = true;
|
||||||
|
node.filters = filters || [];
|
||||||
|
if (this._tree instanceof AsyncServerTree) {
|
||||||
|
await this._tree.rerender(node);
|
||||||
|
}
|
||||||
|
await this.refreshElement(node);
|
||||||
|
await this._tree.expand(node);
|
||||||
|
if (expansionError) {
|
||||||
|
throw new Error(expansionError);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (errorListener) {
|
||||||
|
errorListener.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._telemetryService.createActionEvent(TelemetryKeys.TelemetryView.ObjectExplorer, TelemetryKeys.TelemetryAction.ObjectExplorerFilter)
|
||||||
|
.withAdditionalProperties({
|
||||||
|
filterPropertyNames: JSON.stringify(filters.map(f => node.filterProperties.find(p => f.displayName === p.displayName)?.name)),
|
||||||
|
filterCount: filters.length,
|
||||||
|
objectType: node.objectType
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
this._instantiationService
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter connections based on view (recent/active)
|
* Filter connections based on view (recent/active)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const serverTreeConfig: IConfigurationNode = {
|
|||||||
'properties': {
|
'properties': {
|
||||||
'serverTree.useAsyncServerTree': {
|
'serverTree.useAsyncServerTree': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
'default': true,
|
'default': false,
|
||||||
'description': localize('serverTree.useAsyncServerTree', "Use the new async server tree for the Servers view and Connection Dialog with support for new features such as dynamic node filtering. Requires a restart to take effect.")
|
'description': localize('serverTree.useAsyncServerTree', "Use the new async server tree for the Servers view and Connection Dialog with support for new features such as dynamic node filtering. Requires a restart to take effect.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ suite('ServerTreeView onAddConnectionProfile handler tests', () => {
|
|||||||
);
|
);
|
||||||
mockConnectionManagementService.setup(x => x.getConnectionGroups()).returns(x => []);
|
mockConnectionManagementService.setup(x => x.getConnectionGroups()).returns(x => []);
|
||||||
mockConnectionManagementService.setup(x => x.hasRegisteredServers()).returns(() => true);
|
mockConnectionManagementService.setup(x => x.hasRegisteredServers()).returns(() => true);
|
||||||
serverTreeView = new ServerTreeView(mockConnectionManagementService.object, instantiationService, undefined, new TestThemeService(), undefined, new TestConfigurationService(), capabilitiesService, undefined, undefined, new MockContextKeyService(), undefined, undefined);
|
serverTreeView = new ServerTreeView(mockConnectionManagementService.object, instantiationService, undefined, new TestThemeService(), undefined, new TestConfigurationService(), capabilitiesService, undefined, undefined, new MockContextKeyService(), undefined, undefined, undefined);
|
||||||
mockTree = TypeMoq.Mock.ofType<ITree>(TestTree);
|
mockTree = TypeMoq.Mock.ofType<ITree>(TestTree);
|
||||||
(serverTreeView as any)._tree = mockTree.object;
|
(serverTreeView as any)._tree = mockTree.object;
|
||||||
mockRefreshTreeMethod = TypeMoq.Mock.ofType(Function);
|
mockRefreshTreeMethod = TypeMoq.Mock.ofType(Function);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import { ILogService } from 'vs/platform/log/common/log';
|
|||||||
import { AsyncServerTree, ServerTreeElement } from 'sql/workbench/services/objectExplorer/browser/asyncServerTree';
|
import { AsyncServerTree, ServerTreeElement } from 'sql/workbench/services/objectExplorer/browser/asyncServerTree';
|
||||||
import { SqlIconId } from 'sql/base/common/codicons';
|
import { SqlIconId } from 'sql/base/common/codicons';
|
||||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||||
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
|
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
||||||
|
|
||||||
export interface IServerView {
|
export interface IServerView {
|
||||||
showFilteredTree(filter: string): void;
|
showFilteredTree(filter: string): void;
|
||||||
@@ -310,3 +312,64 @@ export class DeleteConnectionAction extends Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FilterChildrenAction extends Action {
|
||||||
|
public static ID = 'objectExplorer.filterChildren';
|
||||||
|
public static LABEL = localize('objectExplorer.filterChildren', "Filter (Preview)");
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
label: string,
|
||||||
|
private _node: TreeNode,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService) {
|
||||||
|
super(id, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async run(): Promise<void> {
|
||||||
|
await this._objectExplorerService.getServerTreeView().filterElementChildren(this._node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RemoveFilterAction extends Action {
|
||||||
|
public static ID = 'objectExplorer.removeFilter';
|
||||||
|
public static LABEL = localize('objectExplorer.removeFilter', "Remove Filter");
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
label: string,
|
||||||
|
private _node: TreeNode,
|
||||||
|
private _tree: AsyncServerTree | ITree,
|
||||||
|
private _profile: ConnectionProfile | undefined,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
|
@IAdsTelemetryService private _telemetryService: IAdsTelemetryService
|
||||||
|
) {
|
||||||
|
super(id, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async run(): Promise<void> {
|
||||||
|
let node = this._node;
|
||||||
|
let nodeToRefresh: ServerTreeElement = this._node;
|
||||||
|
if (this._profile) {
|
||||||
|
node = this._objectExplorerService.getObjectExplorerNode(this._profile);
|
||||||
|
nodeToRefresh = this._profile;
|
||||||
|
}
|
||||||
|
node.filters = [];
|
||||||
|
if (nodeToRefresh instanceof TreeNode) {
|
||||||
|
nodeToRefresh.forceRefresh = true;
|
||||||
|
}
|
||||||
|
if (this._tree instanceof AsyncServerTree) {
|
||||||
|
await this._tree.rerender(nodeToRefresh);
|
||||||
|
await this._tree.updateChildren(nodeToRefresh);
|
||||||
|
await this._tree.expand(nodeToRefresh);
|
||||||
|
} else {
|
||||||
|
await this._tree.refresh(nodeToRefresh);
|
||||||
|
await this._tree.expand(nodeToRefresh);
|
||||||
|
}
|
||||||
|
this._telemetryService.createActionEvent(
|
||||||
|
TelemetryKeys.TelemetryView.ObjectExplorer,
|
||||||
|
TelemetryKeys.TelemetryAction.ObjectExplorerRemoveFilter
|
||||||
|
).withAdditionalProperties({
|
||||||
|
objectType: node.objectType
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,726 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import 'vs/css!./../media/filterDialog';
|
||||||
|
import { Button } from 'sql/base/browser/ui/button/button';
|
||||||
|
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
|
||||||
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
|
import { Modal } from 'sql/workbench/browser/modal/modal'
|
||||||
|
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration';
|
||||||
|
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||||
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { localize } from 'vs/nls';
|
||||||
|
import { attachModalDialogStyler } from 'sql/workbench/common/styler';
|
||||||
|
import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
|
||||||
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
|
||||||
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
|
import { NodeFilterPropertyDataType, NodeFilterOperator } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
|
import { Table } from 'sql/base/browser/ui/table/table';
|
||||||
|
import { TableCellEditorFactory } from 'sql/base/browser/ui/table/tableCellEditorFactory';
|
||||||
|
import { Emitter } from 'vs/base/common/event';
|
||||||
|
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||||
|
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||||
|
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
||||||
|
import { TableHeaderRowHeight, TableRowHeight } from 'sql/workbench/browser/designer/designerTableUtil';
|
||||||
|
import { textFormatter } from 'sql/base/browser/ui/table/formatters';
|
||||||
|
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/browser/dropdown';
|
||||||
|
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||||
|
import { TabbedPanel } from 'sql/base/browser/ui/panel/panel';
|
||||||
|
import { attachTableStyler } from 'sql/platform/theme/common/styler';
|
||||||
|
import { ButtonColumn } from 'sql/base/browser/ui/table/plugins/buttonColumn.plugin';
|
||||||
|
import Severity from 'vs/base/common/severity';
|
||||||
|
import { status } from 'vs/base/browser/ui/aria/aria';
|
||||||
|
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
|
|
||||||
|
// strings for filter dialog
|
||||||
|
const OkButtonText = localize('objectExplorer.okButtonText', "OK");
|
||||||
|
const CancelButtonText = localize('objectExplorer.cancelButtonText', "Cancel");
|
||||||
|
const ClearAllButtonText = localize('objectExplorer.clearAllButtonText', "Clear All");
|
||||||
|
const TitleIconClass: string = 'icon filterLabel';
|
||||||
|
|
||||||
|
// strings for filter operator select box
|
||||||
|
const EQUALS_SELECT_BOX = localize('objectExplorer.equalsSelectBox', "Equals");
|
||||||
|
const NOT_EQUALS_SELECT_BOX = localize('objectExplorer.notEqualsSelectBox', "Not Equals");
|
||||||
|
const LESS_THAN_SELECT_BOX = localize('objectExplorer.lessThanSelectBox', "Less Than");
|
||||||
|
const LESS_THAN_OR_EQUALS_SELECT_BOX = localize('objectExplorer.lessThanOrEqualsSelectBox', "Less Than Or Equals");
|
||||||
|
const GREATER_THAN_SELECT_BOX = localize('objectExplorer.greaterThanSelectBox', "Greater Than");
|
||||||
|
const GREATER_THAN_OR_EQUALS_SELECT_BOX = localize('objectExplorer.greaterThanOrEqualsSelectBox', "Greater Than Or Equals");
|
||||||
|
const BETWEEN_SELECT_BOX = localize('objectExplorer.betweenSelectBox', "Between");
|
||||||
|
const NOT_BETWEEN_SELECT_BOX = localize('objectExplorer.notBetweenSelectBox', "Not Between");
|
||||||
|
const CONTAINS_SELECT_BOX = localize('objectExplorer.containsSelectBox', "Contains");
|
||||||
|
const NOT_CONTAINS_SELECT_BOX = localize('objectExplorer.notContainsSelectBox', "Not Contains");
|
||||||
|
const AND_SELECT_BOX = localize('objectExplorer.andSelectBox', "And");
|
||||||
|
const IS_NULL_SELECT_BOX = localize('objectExplorer.isNullSelectBox', "Is Null");
|
||||||
|
const IS_NOT_NULL_SELECT_BOX = localize('objectExplorer.isNotNullSelectBox', "Is Not Null");
|
||||||
|
|
||||||
|
// strings for filter table column headers
|
||||||
|
const PROPERTY_NAME_COLUMN_HEADER = localize('objectExplorer.propertyNameColumnHeader', "Property");
|
||||||
|
const OPERATOR_COLUMN_HEADER = localize('objectExplorer.operatorColumnHeader', "Operator");
|
||||||
|
const VALUE_COLUMN_HEADER = localize('objectExplorer.valueColumnHeader', "Value");
|
||||||
|
const CLEAR_COLUMN_HEADER = localize('objectExplorer.clearColumnHeader', "Clear");
|
||||||
|
|
||||||
|
|
||||||
|
// strings for value select box for boolean type filters
|
||||||
|
const TRUE_SELECT_BOX = localize('objectExplorer.trueSelectBox', "True");
|
||||||
|
const FALSE_SELECT_BOX = localize('objectExplorer.falseSelectBox', "False");
|
||||||
|
|
||||||
|
function nodePathDisplayString(nodepath: string): string { return localize('objectExplorer.nodePath', "Node Path: {0}", nodepath) }
|
||||||
|
|
||||||
|
const PROPERTY_COLUMN_ID = 'property';
|
||||||
|
const OPERATOR_COLUMN_ID = 'operator';
|
||||||
|
const VALUE_COLUMN_ID = 'value';
|
||||||
|
const CLEAR_COLUMN_ID = 'clear';
|
||||||
|
|
||||||
|
export class FilterDialog extends Modal {
|
||||||
|
|
||||||
|
private _okButton?: Button;
|
||||||
|
private _cancelButton?: Button;
|
||||||
|
private _clearAllButton?: Button;
|
||||||
|
|
||||||
|
private filterTable: Table<Slick.SlickData>;
|
||||||
|
private _tableCellEditorFactory: TableCellEditorFactory;
|
||||||
|
private _onStyleChangeEventEmitter = new Emitter<void>();
|
||||||
|
private _description: HTMLElement;
|
||||||
|
private _onFilterApplied = new Emitter<azdata.NodeFilter[]>();
|
||||||
|
public readonly onFilterApplied = this._onFilterApplied.event;
|
||||||
|
private _onCloseEvent = new Emitter<void>();
|
||||||
|
public readonly onDialogClose = this._onCloseEvent.event;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _properties: azdata.NodeFilterProperty[],
|
||||||
|
private _filterDialogTitle: string,
|
||||||
|
private _filterDialogSubtitle: string,
|
||||||
|
private _appliedFilters: azdata.NodeFilter[],
|
||||||
|
private applyFilterAction: (filters: azdata.NodeFilter[]) => Promise<void> | undefined,
|
||||||
|
@IThemeService themeService: IThemeService,
|
||||||
|
@IAdsTelemetryService telemetryService: IAdsTelemetryService,
|
||||||
|
@ILayoutService layoutService: ILayoutService,
|
||||||
|
@IClipboardService clipboardService: IClipboardService,
|
||||||
|
@ILogService logService: ILogService,
|
||||||
|
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService,
|
||||||
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
|
@IContextViewService private readonly _contextViewProvider: IContextViewService,
|
||||||
|
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService,
|
||||||
|
@IQuickInputService private readonly _quickInputService: IQuickInputService,
|
||||||
|
@IErrorMessageService private _errorMessageService: IErrorMessageService,
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
'ObjectExplorerServiceDialog',
|
||||||
|
'Object Explorer Service Dialog',
|
||||||
|
telemetryService,
|
||||||
|
layoutService,
|
||||||
|
clipboardService,
|
||||||
|
themeService,
|
||||||
|
logService,
|
||||||
|
textResourcePropertiesService,
|
||||||
|
contextKeyService,
|
||||||
|
{
|
||||||
|
dialogStyle: 'normal',
|
||||||
|
hasTitleIcon: true,
|
||||||
|
hasSpinner: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public open(): void {
|
||||||
|
this.render();
|
||||||
|
this.show();
|
||||||
|
this._okButton.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override render() {
|
||||||
|
super.render();
|
||||||
|
this.title = this._filterDialogTitle;
|
||||||
|
this.titleIconClassName = TitleIconClass;
|
||||||
|
this._register(attachModalDialogStyler(this, this._themeService));
|
||||||
|
this._okButton = this.addFooterButton(OkButtonText, async () => { await this.onApply() });
|
||||||
|
this._cancelButton = this.addFooterButton(CancelButtonText, () => { this.onClose() });
|
||||||
|
this._clearAllButton = this.addFooterButton(ClearAllButtonText, () => { this.onClearAll() }, 'left', true);
|
||||||
|
this._register(attachButtonStyler(this._okButton, this._themeService));
|
||||||
|
this._register(attachButtonStyler(this._cancelButton, this._themeService));
|
||||||
|
this._register(attachButtonStyler(this._clearAllButton, this._themeService));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected renderBody(container: HTMLElement): void {
|
||||||
|
const body = DOM.append(container, DOM.$('.filter-dialog-body'));
|
||||||
|
const subtitle = DOM.append(body, DOM.$('.filter-dialog-node-path'));
|
||||||
|
subtitle.innerText = nodePathDisplayString(this._filterDialogSubtitle);
|
||||||
|
const clauseTableContainer = DOM.append(body, DOM.$('.filter-table-container'));
|
||||||
|
const filter = DOM.append(clauseTableContainer, DOM.$('.filter-table'));
|
||||||
|
this._tableCellEditorFactory = new TableCellEditorFactory(
|
||||||
|
{
|
||||||
|
valueGetter: (item, column): string => {
|
||||||
|
|
||||||
|
// if the operator is And and the operator is date, we need to get the date from the previous
|
||||||
|
// row to make it more user friendly for the user to enter the next value.
|
||||||
|
if (column.field === VALUE_COLUMN_ID && item[OPERATOR_COLUMN_ID].value === AND_SELECT_BOX) {
|
||||||
|
const index = item.filterPropertyIndex;
|
||||||
|
const tableData = this.filterTable.getData().getItems();
|
||||||
|
if (this._properties[index].type === NodeFilterPropertyDataType.Date) {
|
||||||
|
let value1 = '';
|
||||||
|
for (let i = 0; i < tableData.length; i++) {
|
||||||
|
if (tableData[i].filterPropertyIndex === index) {
|
||||||
|
value1 = tableData[i].value.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const value2 = item[column.field].value;
|
||||||
|
return value2 === '' ? value1 : value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item[column.field].value;
|
||||||
|
},
|
||||||
|
valueSetter: (context: any, row: number, item: any, column: Slick.Column<Slick.SlickData>, value: string): void => {
|
||||||
|
item[column.field].value = value;
|
||||||
|
if (column.field === 'operator') {
|
||||||
|
const index = item.filterPropertyIndex;
|
||||||
|
const nodeOperator = this._properties[index].type;
|
||||||
|
if (nodeOperator === NodeFilterPropertyDataType.Date || nodeOperator === NodeFilterPropertyDataType.Number) {
|
||||||
|
if (value === BETWEEN_SELECT_BOX || value === NOT_BETWEEN_SELECT_BOX) {
|
||||||
|
|
||||||
|
const tableData = this.filterTable.getData().getItems();
|
||||||
|
if (tableData.length > row + 1) {
|
||||||
|
if (tableData[row + 1].operator.value === AND_SELECT_BOX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const newRow: Slick.SlickData = {
|
||||||
|
property: {
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
operator: {
|
||||||
|
value: AND_SELECT_BOX,
|
||||||
|
values: [AND_SELECT_BOX]
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: '',
|
||||||
|
values: []
|
||||||
|
},
|
||||||
|
filterPropertyIndex: tableData[row].filterPropertyIndex
|
||||||
|
};
|
||||||
|
const activeElement = this.filterTable.activeCell;
|
||||||
|
tableData.splice(row + 1, 0, newRow);
|
||||||
|
dataProvider.clear();
|
||||||
|
dataProvider.push(tableData);
|
||||||
|
this.filterTable.rerenderGrid();
|
||||||
|
this.filterTable.layout(new DOM.Dimension(600, (dataProvider.getItems().length + 2) * TableRowHeight));
|
||||||
|
this.filterTable.setActiveCell(activeElement.row, activeElement.cell);
|
||||||
|
} else {
|
||||||
|
const tableData = this.filterTable.getData().getItems();
|
||||||
|
if (tableData.length > row + 1) {
|
||||||
|
if (tableData[row + 1].operator.value === AND_SELECT_BOX) {
|
||||||
|
const activeElement = this.filterTable.activeCell;
|
||||||
|
tableData.splice(row + 1, 1);
|
||||||
|
dataProvider.clear();
|
||||||
|
dataProvider.push(tableData);
|
||||||
|
this.filterTable.rerenderGrid();
|
||||||
|
this.filterTable.layout(new DOM.Dimension(600, (dataProvider.getItems().length + 2) * TableRowHeight));
|
||||||
|
this.filterTable.setActiveCell(activeElement.row, activeElement.cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
optionsGetter: (item, column): string[] => {
|
||||||
|
return item[column.field].values;
|
||||||
|
},
|
||||||
|
editorStyler: (component) => {
|
||||||
|
this.styleComponent(component);
|
||||||
|
},
|
||||||
|
onStyleChange: this._onStyleChangeEventEmitter.event
|
||||||
|
}, this._contextViewProvider
|
||||||
|
);
|
||||||
|
const columns: Slick.Column<Slick.SlickData>[] = [
|
||||||
|
{
|
||||||
|
id: PROPERTY_COLUMN_ID,
|
||||||
|
name: PROPERTY_NAME_COLUMN_HEADER,
|
||||||
|
field: PROPERTY_COLUMN_ID,
|
||||||
|
formatter: textFormatter,
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: OPERATOR_COLUMN_ID,
|
||||||
|
name: OPERATOR_COLUMN_HEADER,
|
||||||
|
editor: this._tableCellEditorFactory.getDropdownEditorClass(this, [], false),
|
||||||
|
field: OPERATOR_COLUMN_ID,
|
||||||
|
formatter: textFormatter,
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: VALUE_COLUMN_ID,
|
||||||
|
name: VALUE_COLUMN_HEADER,
|
||||||
|
width: 180,
|
||||||
|
formatter: textFormatter,
|
||||||
|
field: VALUE_COLUMN_ID
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const clearValueColumn = new ButtonColumn({
|
||||||
|
id: CLEAR_COLUMN_ID,
|
||||||
|
iconCssClass: 'icon erase',
|
||||||
|
name: CLEAR_COLUMN_HEADER,
|
||||||
|
title: CLEAR_COLUMN_HEADER,
|
||||||
|
width: 60,
|
||||||
|
resizable: true,
|
||||||
|
isFontIcon: true
|
||||||
|
});
|
||||||
|
this._register(clearValueColumn.onClick(e => {
|
||||||
|
const row = e.row;
|
||||||
|
const data = this.filterTable.getData().getItems();
|
||||||
|
data[row][VALUE_COLUMN_ID].value = '';
|
||||||
|
dataProvider.clear();
|
||||||
|
dataProvider.push(data);
|
||||||
|
this.filterTable.rerenderGrid();
|
||||||
|
}));
|
||||||
|
columns.push(clearValueColumn.definition);
|
||||||
|
|
||||||
|
|
||||||
|
const tableData: Slick.SlickData[] = [];
|
||||||
|
if (!this._appliedFilters) {
|
||||||
|
this._appliedFilters = [];
|
||||||
|
}
|
||||||
|
this._properties.forEach((f, i) => {
|
||||||
|
const appliedFilter = this._appliedFilters.find(filter => filter.displayName === f.displayName);
|
||||||
|
const filterOperators = this.getOperatorsForType(f.type);
|
||||||
|
const row: Slick.SlickData = {
|
||||||
|
property: {
|
||||||
|
value: f.displayName
|
||||||
|
},
|
||||||
|
operator: {
|
||||||
|
value: appliedFilter ? this.getFilterOperatorString(appliedFilter.operator) : filterOperators[0],
|
||||||
|
values: filterOperators
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: appliedFilter ? this.getStringValueForFilter(f, appliedFilter.value) : '',
|
||||||
|
values: this.getChoiceValuesForFilterProperties(f)
|
||||||
|
},
|
||||||
|
filterPropertyIndex: i
|
||||||
|
};
|
||||||
|
tableData.push(row);
|
||||||
|
|
||||||
|
if (appliedFilter?.operator === NodeFilterOperator.Between || appliedFilter?.operator === NodeFilterOperator.NotBetween) {
|
||||||
|
row.value.value = this.getStringValueForFilter(f, appliedFilter.value[0]);
|
||||||
|
const andRow: Slick.SlickData = {
|
||||||
|
property: {
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
operator: {
|
||||||
|
value: AND_SELECT_BOX,
|
||||||
|
values: [AND_SELECT_BOX]
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: this.getStringValueForFilter(f, appliedFilter.value[1]),
|
||||||
|
values: []
|
||||||
|
},
|
||||||
|
datatype: f.type,
|
||||||
|
filterPropertyIndex: i
|
||||||
|
};
|
||||||
|
tableData.push(andRow);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataProvider = new TableDataView<Slick.SlickData>();
|
||||||
|
dataProvider.push(tableData);
|
||||||
|
|
||||||
|
|
||||||
|
// Sets up the editor for the value column
|
||||||
|
(<any>dataProvider).getItemMetadata = (row: number) => {
|
||||||
|
const rowData = dataProvider.getItem(row);
|
||||||
|
|
||||||
|
const filterProperty = this._properties[rowData.filterPropertyIndex];
|
||||||
|
let editor;
|
||||||
|
if (rowData.operator.value === AND_SELECT_BOX) {
|
||||||
|
if (filterProperty.type === NodeFilterPropertyDataType.Number) {
|
||||||
|
editor = this._tableCellEditorFactory.getTextEditorClass(this, 'number');
|
||||||
|
} else if (filterProperty.type === NodeFilterPropertyDataType.Date) {
|
||||||
|
editor = this._tableCellEditorFactory.getTextEditorClass(this, 'date');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (filterProperty.type === NodeFilterPropertyDataType.String) {
|
||||||
|
editor = this._tableCellEditorFactory.getTextEditorClass(this, 'text');
|
||||||
|
} else if (filterProperty.type === NodeFilterPropertyDataType.Date) {
|
||||||
|
editor = this._tableCellEditorFactory.getTextEditorClass(this, 'date');
|
||||||
|
} else if (filterProperty.type === NodeFilterPropertyDataType.Boolean) {
|
||||||
|
editor = this._tableCellEditorFactory.getDropdownEditorClass(this, [TRUE_SELECT_BOX, FALSE_SELECT_BOX], false);
|
||||||
|
} else if (filterProperty.type === NodeFilterPropertyDataType.Number) {
|
||||||
|
editor = this._tableCellEditorFactory.getTextEditorClass(this, 'number');
|
||||||
|
} else if (filterProperty.type === NodeFilterPropertyDataType.Choice) {
|
||||||
|
editor = this._tableCellEditorFactory.getDropdownEditorClass(this, this.getDropdownOptionsForChoiceProperty(<azdata.NodeFilterChoiceProperty>filterProperty), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
columns: {
|
||||||
|
value: {
|
||||||
|
editor: editor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.filterTable = new Table(filter, this._accessibilityService, this._quickInputService, {
|
||||||
|
dataProvider: dataProvider!,
|
||||||
|
columns: columns,
|
||||||
|
}, {
|
||||||
|
editable: true,
|
||||||
|
autoEdit: true,
|
||||||
|
dataItemColumnValueExtractor: (data: any, column: Slick.Column<Slick.SlickData>): string => {
|
||||||
|
if (column.field) {
|
||||||
|
return data[column.field]?.value;
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowHeight: TableRowHeight,
|
||||||
|
headerRowHeight: TableHeaderRowHeight,
|
||||||
|
editorLock: new Slick.EditorLock(),
|
||||||
|
autoHeight: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.filterTable.grid.onActiveCellChanged.subscribe((e, any) => {
|
||||||
|
if (this.filterTable.grid.getActiveCell()) {
|
||||||
|
const row = this.filterTable.grid.getActiveCell().row;
|
||||||
|
const data = this.filterTable.getData().getItems()[row];
|
||||||
|
let index = data.filterPropertyIndex;
|
||||||
|
const filterPropertyDescription = this._properties[index].description;
|
||||||
|
this._description.innerText = filterPropertyDescription;
|
||||||
|
// Announcing the filter property description for screen reader users
|
||||||
|
status(filterPropertyDescription);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.filterTable.registerPlugin(clearValueColumn);
|
||||||
|
this.filterTable.layout(new DOM.Dimension(600, (tableData.length + 2) * TableRowHeight));
|
||||||
|
this._register(attachTableStyler(this.filterTable, this._themeService));
|
||||||
|
|
||||||
|
this._description = DOM.append(body, DOM.$('.filter-dialog-description'));
|
||||||
|
this._description.innerHTML = this._properties[0].description;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected layout(height?: number): void {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override onClose() {
|
||||||
|
this.hide('close');
|
||||||
|
this._onCloseEvent.fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onClearAll() {
|
||||||
|
const tableAllData = this.filterTable.getData().getItems();
|
||||||
|
tableAllData.forEach((row) => {
|
||||||
|
row.value.value = '';
|
||||||
|
|
||||||
|
});
|
||||||
|
this.filterTable.rerenderGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is called when the ok button is pressed
|
||||||
|
private async onApply(): Promise<void> {
|
||||||
|
const tableData = this.filterTable.getData().getItems();
|
||||||
|
|
||||||
|
this._appliedFilters = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < tableData.length; i++) {
|
||||||
|
const row = tableData[i];
|
||||||
|
let filterProperty = this._properties[row.filterPropertyIndex]
|
||||||
|
let filter: azdata.NodeFilter = {
|
||||||
|
displayName: row.property.value,
|
||||||
|
operator: this.getFilterOperatorEnum(row.operator.value),
|
||||||
|
value: this.getFilterValue(filterProperty.type, row.value.value, filterProperty),
|
||||||
|
};
|
||||||
|
|
||||||
|
const isMultipleValueFilter = filter.operator === NodeFilterOperator.Between || filter.operator === NodeFilterOperator.NotBetween;
|
||||||
|
if (isMultipleValueFilter) {
|
||||||
|
i++;
|
||||||
|
const row2 = tableData[i];
|
||||||
|
var value1 = this.getFilterValue(filterProperty.type, row.value.value, filterProperty);
|
||||||
|
var value2 = this.getFilterValue(filterProperty.type, row2.value.value, filterProperty);
|
||||||
|
filter.value = <string[] | number[]>[value1, value2];
|
||||||
|
if (filterProperty.type === NodeFilterPropertyDataType.Date) {
|
||||||
|
if (filter.value[0] === '' && filter.value[1] !== '') {
|
||||||
|
// start date not specified.
|
||||||
|
this._errorMessageService.showDialog(Severity.Error, '', localize('filterDialog.errorStartDate', "Start date is not specified."));
|
||||||
|
return;
|
||||||
|
} else if (filter.value[0] !== '' && filter.value[1] === '') {
|
||||||
|
// end date not specified.
|
||||||
|
this._errorMessageService.showDialog(Severity.Error, '', localize('filterDialog.errorEndDate', "End date is not specified."));
|
||||||
|
return;
|
||||||
|
} else if (new Date(filter.value[0]) > new Date(filter.value[1])) {
|
||||||
|
// start date is greater than end date.
|
||||||
|
this._errorMessageService.showDialog(Severity.Error, '', localize('filterDialog.errorDateRange', "Start date cannot be greater than end date."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (filterProperty.type === NodeFilterPropertyDataType.Number) {
|
||||||
|
if (filter.value[0] === '' && filter.value[1] !== '') {
|
||||||
|
// start number not specified.
|
||||||
|
this._errorMessageService.showDialog(Severity.Error, '', localize('filterDialog.errorStartNumber', "Start number is not specified."));
|
||||||
|
return;
|
||||||
|
} else if (filter.value[0] !== '' && filter.value[1] === '') {
|
||||||
|
// end number not specified.
|
||||||
|
this._errorMessageService.showDialog(Severity.Error, '', localize('filterDialog.errorEndNumber', "End number is not specified."));
|
||||||
|
return;
|
||||||
|
} else if (Number(filter.value[0]) > Number(filter.value[1])) {
|
||||||
|
// start number is greater than end number.
|
||||||
|
this._errorMessageService.showDialog(Severity.Error, '', localize('filterDialog.errorNumberRange', "Start number cannot be greater than end number."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (value1 !== '' && value2 !== '') {
|
||||||
|
this._appliedFilters.push(filter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (filter.value !== '') {
|
||||||
|
this._appliedFilters.push(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.spinner = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (this.applyFilterAction) {
|
||||||
|
await this.applyFilterAction(this._appliedFilters);
|
||||||
|
}
|
||||||
|
this._onFilterApplied.fire(this._appliedFilters);
|
||||||
|
this.hide('ok');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
this.spinner = false;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is called by modal when the enter button is pressed
|
||||||
|
// We override it to do nothing so that the enter button doesn't close the dialog
|
||||||
|
protected override async onAccept() {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
private getFilterValue(
|
||||||
|
filterType: NodeFilterPropertyDataType,
|
||||||
|
value: string,
|
||||||
|
filterProperty: azdata.NodeFilterProperty
|
||||||
|
): string | number | boolean {
|
||||||
|
if (value === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
switch (filterType) {
|
||||||
|
case NodeFilterPropertyDataType.Boolean:
|
||||||
|
if (value === TRUE_SELECT_BOX) {
|
||||||
|
return true;
|
||||||
|
} else if (value === FALSE_SELECT_BOX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case NodeFilterPropertyDataType.Number:
|
||||||
|
return Number(value);
|
||||||
|
case NodeFilterPropertyDataType.Choice:
|
||||||
|
const choice = ((<azdata.NodeFilterChoiceProperty>filterProperty).choices.find(c => c.displayName === value));
|
||||||
|
if (choice) {
|
||||||
|
return choice.value;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
case NodeFilterPropertyDataType.Date:
|
||||||
|
case NodeFilterPropertyDataType.String:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getStringValueForFilter(filter: azdata.NodeFilterProperty, value: string | number | boolean | number[] | string[]): string {
|
||||||
|
switch (filter.type) {
|
||||||
|
case NodeFilterPropertyDataType.Boolean:
|
||||||
|
if (value === true) {
|
||||||
|
return TRUE_SELECT_BOX;
|
||||||
|
} else if (value === false) {
|
||||||
|
return FALSE_SELECT_BOX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NodeFilterPropertyDataType.Number:
|
||||||
|
return value.toString();
|
||||||
|
case NodeFilterPropertyDataType.Choice:
|
||||||
|
return (<azdata.NodeFilterChoiceProperty>filter).choices.find(c => c.value === value).displayName;
|
||||||
|
case NodeFilterPropertyDataType.Date:
|
||||||
|
case NodeFilterPropertyDataType.String:
|
||||||
|
return value as string;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private getOperatorsForType(type: NodeFilterPropertyDataType): string[] {
|
||||||
|
switch (type) {
|
||||||
|
case NodeFilterPropertyDataType.String:
|
||||||
|
return [
|
||||||
|
CONTAINS_SELECT_BOX,
|
||||||
|
NOT_CONTAINS_SELECT_BOX,
|
||||||
|
EQUALS_SELECT_BOX,
|
||||||
|
NOT_EQUALS_SELECT_BOX
|
||||||
|
];
|
||||||
|
case NodeFilterPropertyDataType.Number:
|
||||||
|
return [
|
||||||
|
EQUALS_SELECT_BOX,
|
||||||
|
NOT_EQUALS_SELECT_BOX,
|
||||||
|
GREATER_THAN_SELECT_BOX,
|
||||||
|
GREATER_THAN_OR_EQUALS_SELECT_BOX,
|
||||||
|
LESS_THAN_SELECT_BOX,
|
||||||
|
LESS_THAN_OR_EQUALS_SELECT_BOX,
|
||||||
|
BETWEEN_SELECT_BOX,
|
||||||
|
NOT_BETWEEN_SELECT_BOX
|
||||||
|
];
|
||||||
|
case NodeFilterPropertyDataType.Boolean:
|
||||||
|
return [
|
||||||
|
EQUALS_SELECT_BOX,
|
||||||
|
NOT_EQUALS_SELECT_BOX
|
||||||
|
];
|
||||||
|
case NodeFilterPropertyDataType.Choice:
|
||||||
|
return [
|
||||||
|
EQUALS_SELECT_BOX,
|
||||||
|
NOT_EQUALS_SELECT_BOX
|
||||||
|
];
|
||||||
|
case NodeFilterPropertyDataType.Date:
|
||||||
|
return [
|
||||||
|
EQUALS_SELECT_BOX,
|
||||||
|
NOT_EQUALS_SELECT_BOX,
|
||||||
|
GREATER_THAN_SELECT_BOX,
|
||||||
|
GREATER_THAN_OR_EQUALS_SELECT_BOX,
|
||||||
|
LESS_THAN_SELECT_BOX,
|
||||||
|
LESS_THAN_OR_EQUALS_SELECT_BOX,
|
||||||
|
BETWEEN_SELECT_BOX,
|
||||||
|
NOT_BETWEEN_SELECT_BOX
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getFilterOperatorString(operator: NodeFilterOperator): string {
|
||||||
|
switch (operator) {
|
||||||
|
case NodeFilterOperator.Contains:
|
||||||
|
return CONTAINS_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.NotContains:
|
||||||
|
return NOT_CONTAINS_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.Equals:
|
||||||
|
return EQUALS_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.NotEquals:
|
||||||
|
return NOT_EQUALS_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.GreaterThan:
|
||||||
|
return GREATER_THAN_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.GreaterThanOrEquals:
|
||||||
|
return GREATER_THAN_OR_EQUALS_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.LessThan:
|
||||||
|
return LESS_THAN_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.LessThanOrEquals:
|
||||||
|
return LESS_THAN_OR_EQUALS_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.Between:
|
||||||
|
return BETWEEN_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.NotBetween:
|
||||||
|
return NOT_BETWEEN_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.IsNull:
|
||||||
|
return IS_NULL_SELECT_BOX;
|
||||||
|
case NodeFilterOperator.IsNotNull:
|
||||||
|
return IS_NOT_NULL_SELECT_BOX;
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getFilterOperatorEnum(operator: string): NodeFilterOperator {
|
||||||
|
switch (operator) {
|
||||||
|
case CONTAINS_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.Contains;
|
||||||
|
case NOT_CONTAINS_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.NotContains;
|
||||||
|
case EQUALS_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.Equals;
|
||||||
|
case NOT_EQUALS_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.NotEquals;
|
||||||
|
case GREATER_THAN_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.GreaterThan;
|
||||||
|
case GREATER_THAN_OR_EQUALS_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.GreaterThanOrEquals;
|
||||||
|
case LESS_THAN_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.LessThan;
|
||||||
|
case LESS_THAN_OR_EQUALS_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.LessThanOrEquals;
|
||||||
|
case BETWEEN_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.Between;
|
||||||
|
case NOT_BETWEEN_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.NotBetween;
|
||||||
|
case TRUE_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.Equals;
|
||||||
|
case FALSE_SELECT_BOX:
|
||||||
|
return NodeFilterOperator.NotEquals;
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getChoiceValuesForFilterProperties(f: azdata.NodeFilterProperty): string[] {
|
||||||
|
switch (f.type) {
|
||||||
|
case NodeFilterPropertyDataType.Boolean:
|
||||||
|
return ['', TRUE_SELECT_BOX, FALSE_SELECT_BOX];
|
||||||
|
case NodeFilterPropertyDataType.Choice:
|
||||||
|
return ['', ...this.getDropdownOptionsForChoiceProperty(<azdata.NodeFilterChoiceProperty>f)];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDropdownOptionsForChoiceProperty(f: azdata.NodeFilterChoiceProperty): string[] {
|
||||||
|
return f.choices.map(choice => {
|
||||||
|
return choice.displayName ?? choice.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private styleComponent(component: TabbedPanel | InputBox | Checkbox | Table<Slick.SlickData> | SelectBox | Button | Dropdown): void {
|
||||||
|
if (component instanceof InputBox) {
|
||||||
|
this._register(attachInputBoxStyler(component, this._themeService));
|
||||||
|
} else if (component instanceof SelectBox) {
|
||||||
|
this._register(attachSelectBoxStyler(component, this._themeService));
|
||||||
|
} else if (component instanceof Table) {
|
||||||
|
this._register(attachTableStyler(component, this._themeService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to let user apply filters on the given filters properties.
|
||||||
|
* @param properties Properties on which user can apply filters.
|
||||||
|
* @param filterDialogTitle Title of the filter dialog.
|
||||||
|
* @param filterDialogSubtile Subtitle of the filter dialog.
|
||||||
|
* @param appliedFilters Filters that are already applied so that we can prepopulate the filter dialog values.
|
||||||
|
* @param applyFilterAction Action to be performed when user clicks on apply button. We should pass this so that we can handle the spinner and error message within the dialog.
|
||||||
|
* @param instantiationService Instantiation service to create the filter dialog.
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public static async getFiltersForProperties(
|
||||||
|
properties: azdata.NodeFilterProperty[],
|
||||||
|
filterDialogTitle: string,
|
||||||
|
filterDialogSubtile: string,
|
||||||
|
appliedFilters: azdata.NodeFilter[] | undefined,
|
||||||
|
applyFilterAction: (filters: azdata.NodeFilter[]) => Promise<void> | undefined,
|
||||||
|
instantiationService: IInstantiationService,
|
||||||
|
): Promise<azdata.NodeFilter[]> {
|
||||||
|
|
||||||
|
const dialog = instantiationService.createInstance(FilterDialog, properties, filterDialogTitle, filterDialogSubtile, appliedFilters, applyFilterAction);
|
||||||
|
dialog.open();
|
||||||
|
return new Promise<azdata.NodeFilter[]>((resolve, reject) => {
|
||||||
|
dialog.onFilterApplied(filters => {
|
||||||
|
resolve(filters);
|
||||||
|
});
|
||||||
|
dialog.onDialogClose(() => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048">
|
||||||
|
<path fill="#fff" d="M1115 1792h421v128H453L50 1516q-24-24-37-56t-13-68q0-35 13-67t38-58L1248 69l794 795-927 928zm133-1542L538 960l614 613 709-709-613-614zM933 1792l128-128-613-614-306 307q-14 14-14 35t14 35l364 365h427z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 299 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user