First sketch of the extension, adds search in explorer and lists services

This commit is contained in:
Pablo Castro 2019-05-26 19:41:17 -07:00
Родитель fd2a29831f
Коммит aa8b73ee9f
24 изменённых файлов: 10766 добавлений и 1 удалений

4
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
out
node_modules
.vscode-test/
*.vsix

7
.vscode/extensions.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"ms-vscode.vscode-typescript-tslint-plugin"
]
}

35
.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,35 @@
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "npm: watch"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test"
],
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "npm: watch"
}
]
}

11
.vscode/settings.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off"
}

20
.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "watch",
"problemMatcher": "$tsc-watch",
"isBackground": true,
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

9
.vscodeignore Normal file
Просмотреть файл

@ -0,0 +1,9 @@
.vscode/**
.vscode-test/**
out/test/**
src/**
.gitignore
**/tsconfig.json
**/tslint.json
**/*.map
**/*.ts

5
CHANGELOG.md Normal file
Просмотреть файл

@ -0,0 +1,5 @@
# Change Log
## [Unreleased]
- Initial release

Просмотреть файл

@ -1 +1,21 @@
# vscode-azuresearch
# Azure Search for Visual Studio Code (Preview)
Azure Search is a Microsoft-managed service for understanding, indexing and searching content of all nature, from databases to blobs to custom content.
## Features
* Browse Azure Search services
* Inspect service details including replicas, partitions, etc.
* List indexes in each service
## Extension Settings
This extension contributes the following settings:
* `azureSearch.showExplorer`: enable/disable showing Azure Search in the Azure explorer window
## Release Notes
### 0.0.1
TBD

10298
package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

130
package.json Normal file
Просмотреть файл

@ -0,0 +1,130 @@
{
"name": "vscode-azuresearch",
"displayName": "Azure Search",
"description": "Manage your Azure Search services",
"version": "0.0.1",
"publisher": "pmc",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
"vscode": "^1.34.0"
},
"categories": [
"Azure"
],
"keywords": [
"Azure",
"Search"
],
"preview": true,
"activationEvents": [
"onView:azureSearch",
"onCommand:azureSearch.refresh",
"onCommand:azureSearch.openInPortal",
"onCommand:azureSearch.selectSubscriptions"
],
"main": "./out/extension.js",
"contributes": {
"viewsContainers": {
"activitybar": [
{
"id": "azure",
"title": "Azure",
"icon": "resources/azure.svg"
}
]
},
"views": {
"azure": [
{
"id": "azureSearch",
"name": "Search",
"when": "config.azureSearch.showExplorer == true"
}
]
},
"commands": [
{
"command": "azureSearch.refresh",
"title": "Refresh",
"icon": {
"light": "resources/light/refresh.svg",
"dark": "resources/dark/refresh.svg"
},
"category": "Azure Search"
},
{
"command": "azureSearch.openInPortal",
"title": "Open in Portal",
"category": "Azure Search"
},
{
"command": "azureSearch.selectSubscriptions",
"title": "Select Subscriptions...",
"icon": {
"light": "resources/light/filter.svg",
"dark": "resources/dark/filter.svg"
},
"category": "Azure Search"
}
],
"menus": {
"view/title": [
{
"command": "azureSearch.refresh",
"when": "view == azureSearch",
"group": "navigation@99"
}
],
"view/item/context": [
{
"command": "azureSearch.selectSubscriptions",
"when": "view == azureSearch && viewItem == azureextensionui.azureSubscription",
"group": "inline"
},
{
"command": "azureSearch.refresh",
"when": "view == azureSearch && viewItem == azureextensionui.azureSubscription",
"group": "9_refresh"
},
{
"command": "azureSearch.openInPortal",
"when": "view == azureSearch && viewItem == azureSearchService",
"group": "navigation@2"
}
]
},
"configuration": {
"title": "Azure Search Services",
"properties": {
"azureSearch.showExplorer": {
"type": "boolean",
"default": true,
"description": "Show or hide the Azure Search Explorer"
}
}
}
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"postinstall": "node ./node_modules/vscode/bin/install",
"test": "npm run compile && node ./node_modules/vscode/bin/test"
},
"extensionDependencies": [
"ms-vscode.azure-account"
],
"devDependencies": {
"typescript": "^3.3.1",
"vscode": "^1.1.28",
"tslint": "^5.12.1",
"@types/node": "^10.12.21",
"@types/mocha": "^2.2.42",
"vscode-azureextensiondev": "0.1.8"
},
"dependencies": {
"azure-arm-resource": "^7.3.0",
"azure-arm-search": "^1.3.0-preview",
"vscode-azureextensionui": "^0.25.0"
}
}

6
resources/azure.svg Normal file
Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="28" width="28" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#0072C6" d="M11.423,44.326l23.623-4.156L22.894,25.748l6.328-17.346L50,44.33L11.423,44.326z M27.566,5.67L11.469,40.109v-0.034H0l12.717-21.975L27.566,5.67z" />
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 331 B

Просмотреть файл

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 0v3.043l5 6V16h6V9.043l5-6V0H0z" id="outline" style="display: none;"/><path class="icon-vs-fg" d="M7 14h2V8.319l5-6V2H2v.319l5 6V14z" id="iconFg" style="display: none;"/><path class="icon-vs-bg" d="M10 15H6V8.681l-5-6V1h14v1.681l-5 6V15zm-3-1h2V8.319l5-6V2H2v.319l5 6V14z" id="iconBg"/></svg>

После

Ширина:  |  Высота:  |  Размер: 596 B

Просмотреть файл

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#2D2D30"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#C5C5C5"/></svg>

После

Ширина:  |  Высота:  |  Размер: 986 B

Просмотреть файл

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 0v3.043l5 6V16h6V9.043l5-6V0H0z" id="outline" style="display: none;"/><path class="icon-vs-fg" d="M7 14h2V8.319l5-6V2H2v.319l5 6V14z" id="iconFg" style="display: none;"/><path class="icon-vs-bg" d="M10 15H6V8.681l-5-6V1h14v1.681l-5 6V15zm-3-1h2V8.319l5-6V2H2v.319l5 6V14z" id="iconBg"/></svg>

После

Ширина:  |  Высота:  |  Размер: 596 B

Просмотреть файл

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#F6F6F6"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#424242"/></svg>

После

Ширина:  |  Высота:  |  Размер: 986 B

Просмотреть файл

@ -0,0 +1,8 @@
import { AzureAccountTreeItemBase, ISubscriptionContext } from "vscode-azureextensionui";
import { SubscriptionTreeItem } from "./SubscriptionTreeItem";
export class AzureAccountTreeItem extends AzureAccountTreeItemBase {
public createSubscriptionTreeItem(root: ISubscriptionContext): SubscriptionTreeItem {
return new SubscriptionTreeItem(this, root);
}
}

Просмотреть файл

@ -0,0 +1,34 @@
import { AzureParentTreeItem, IActionContext, AzExtTreeItem, GenericTreeItem } from "vscode-azureextensionui";
import { isNullOrUndefined } from "util";
import { SearchService } from "azure-arm-search/lib/models";
import SearchManagementClient from "azure-arm-search";
export class SearchServiceTreeItem extends AzureParentTreeItem {
public static contextValue: string = "azureSearchService";
public readonly contextValue: string = SearchServiceTreeItem.contextValue;
public label: string = isNullOrUndefined(this.searchService.name) ? "InvalidSearchService" : this.searchService.name;
public constructor(
parent: AzureParentTreeItem,
public readonly searchService: SearchService,
public readonly searchManagementClient: SearchManagementClient) {
super(parent);
}
public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise<AzExtTreeItem[]> {
let items: AzExtTreeItem[] = [];
items.push(new GenericTreeItem(this, { label: "Service details", contextValue: "azureSearchServiceDetails" }));
items.push(new GenericTreeItem(this, { label: "Indexes", contextValue: "azureSearchIndexes" }));
// TODO: Other pending subresources of search services
// items.push(new GenericTreeItem(this, { label: "Synonym maps", contextValue: "azureSearchSynonymMaps" }));
// items.push(new GenericTreeItem(this, { label: "Data Sources", contextValue: "azureSearchDataSources" }));
// items.push(new GenericTreeItem(this, { label: "Indexers", contextValue: "azureSearchIndexers" }));
// items.push(new GenericTreeItem(this, { label: "Skillsets", contextValue: "azureSearchSkillsets" }));
return items;
}
public hasMoreChildrenImpl(): boolean {
return false;
}
}

Просмотреть файл

@ -0,0 +1,40 @@
import { SearchManagementClient } from 'azure-arm-search';
import { ResourceManagementClient } from 'azure-arm-resource';
import { SearchService } from 'azure-arm-search/lib/models';
import { AzExtTreeItem, createAzureClient, SubscriptionTreeItemBase, addExtensionUserAgent } from 'vscode-azureextensionui';
import { SearchServiceTreeItem } from './SearchServiceTreeItem';
export class SubscriptionTreeItem extends SubscriptionTreeItemBase {
private _nextLink: string | undefined;
public childTypeLabel: string = "Search Service";
async loadMoreChildrenImpl(_clearCache: boolean): Promise<AzExtTreeItem[]> {
if (_clearCache) {
this._nextLink = undefined;
}
// The pattern to follow is this:
// let searchManagementClient = createAzureClient(this.root, SearchManagementClient);
// but SearchManagementClient defaults to an API version that the Search RP doesn't support. Will get that fixed.
const searchManagementClient = new SearchManagementClient(this.root.credentials, this.root.subscriptionId, this.root.environment.resourceManagerEndpointUrl);
searchManagementClient.apiVersion = "2015-02-28";
addExtensionUserAgent(searchManagementClient);
const resourceManagementClient = createAzureClient(this.root, ResourceManagementClient.ResourceManagementClient);
const services = !this._nextLink ?
await resourceManagementClient.resources.list({ filter: "resourceType eq 'Microsoft.Search/searchServices'" }) :
await resourceManagementClient.resources.listNext(this._nextLink);
this._nextLink = services.nextLink;
return this.createTreeItemsWithErrorHandling(
services,
'invalidSearchService',
async (s: SearchService) => await new SearchServiceTreeItem(this, s, searchManagementClient),
(s: SearchService) => s.name
);
}
public hasMoreChildrenImpl(): boolean {
return !!this._nextLink;
}
}

41
src/extension.ts Normal file
Просмотреть файл

@ -0,0 +1,41 @@
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import { ext } from './extensionVariables';
import { createTelemetryReporter, AzureUserInput, registerUIExtensionVariables, AzExtTreeDataProvider, IActionContext, AzExtTreeItem, registerCommand, createApiProvider, AzureTreeItem } from 'vscode-azureextensionui';
import { AzureAccountTreeItem } from './AzureAccountTreeItem';
import { SearchServiceTreeItem } from './SearchServiceTreeItem';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
ext.context = context;
ext.reporter = createTelemetryReporter(context);
ext.ui = new AzureUserInput(context.globalState);
ext.outputChannel = vscode.window.createOutputChannel("Azure Search");
context.subscriptions.push(ext.outputChannel);
registerUIExtensionVariables(ext);
const azureAccountTreeItem = new AzureAccountTreeItem();
context.subscriptions.push(azureAccountTreeItem);
ext.tree = new AzExtTreeDataProvider(azureAccountTreeItem, 'azureSearch.loadMore');
ext.treeView = vscode.window.createTreeView('azureSearch', { treeDataProvider: ext.tree });
context.subscriptions.push(ext.treeView);
registerCommand('azureSearch.refresh', async (_actionContext: IActionContext, treeItem?: AzExtTreeItem) => ext.tree.refresh(treeItem));
registerCommand('azureSearch.loadMore', async (actionContext: IActionContext, treeItem: AzExtTreeItem) => await ext.tree.loadMore(treeItem, actionContext));
registerCommand('azureSearch.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions"));
registerCommand("azureSearch.openInPortal", async (actionContext: IActionContext, treeItem?: AzureTreeItem) => {
if (!treeItem) {
treeItem = <SearchServiceTreeItem>await ext.tree.showTreeItemPicker(SearchServiceTreeItem.contextValue, actionContext);
}
await treeItem.openInPortal();
});
return createApiProvider([]);
}
// this method is called when your extension is deactivated
export function deactivate() {}

12
src/extensionVariables.ts Normal file
Просмотреть файл

@ -0,0 +1,12 @@
import { ExtensionContext, OutputChannel, TreeView } from "vscode";
import { AzExtTreeDataProvider, AzExtTreeItem, IAzureUserInput, ITelemetryReporter } from "vscode-azureextensionui";
export namespace ext {
export let context: ExtensionContext;
export let outputChannel: OutputChannel;
export let ui: IAzureUserInput;
export let reporter: ITelemetryReporter;
export let tree: AzExtTreeDataProvider;
export let treeView: TreeView<AzExtTreeItem>;
}

Просмотреть файл

@ -0,0 +1,22 @@
//
// Note: This example test is leveraging the Mocha test framework.
// Please refer to their documentation on https://mochajs.org/ for help.
//
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
// import * as vscode from 'vscode';
// import * as myExtension from '../extension';
// Defines a Mocha test suite to group tests of similar kind together
suite("Extension Tests", function () {
// Defines a Mocha unit test
test("Something 1", function() {
assert.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
});

23
src/test/index.ts Normal file
Просмотреть файл

@ -0,0 +1,23 @@
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testsRoot: string, clb: (error: Error, failures?: number) => void): void
// that the extension host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.
import * as testRunner from 'vscode/lib/testrunner';
// You can directly control Mocha options by configuring the test runner below
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options
// for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
useColors: true // colored output from test results
});
module.exports = testRunner;

21
tsconfig.json Normal file
Просмотреть файл

@ -0,0 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "out",
"lib": [
"es6"
],
"sourceMap": true,
"rootDir": "src",
"strict": true /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
},
"exclude": [
"node_modules",
".vscode-test"
]
}

15
tslint.json Normal file
Просмотреть файл

@ -0,0 +1,15 @@
{
"rules": {
"no-string-throw": true,
"no-unused-expression": true,
"no-duplicate-variable": true,
"curly": true,
"class-name": true,
"semicolon": [
true,
"always"
],
"triple-equals": true
},
"defaultSeverity": "warning"
}