Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start implementation of compat shim #358

Merged
merged 87 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
9b165fc
Start implementation of compat shim
bwateratmsft Aug 10, 2022
37bc0f2
Minor edits
bwateratmsft Aug 11, 2022
1f016b4
Merge branch 'philliphoff-resource-api' into bmw/philliphoff-resource…
bwateratmsft Aug 15, 2022
224f71a
Add subscription info
bwateratmsft Aug 15, 2022
46f86f3
Minor changes to API
bwateratmsft Aug 15, 2022
6329934
Minor change
bwateratmsft Aug 15, 2022
871c257
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
bwateratmsft Sep 8, 2022
08c9b83
Current changes
bwateratmsft Sep 8, 2022
75acdd9
Comment addition
bwateratmsft Sep 8, 2022
b4711b4
Commit rough progress
bwateratmsft Sep 9, 2022
f1eefe3
Renaming to wrapper
bwateratmsft Sep 9, 2022
caa0ab2
More renaming
bwateratmsft Sep 9, 2022
a10244e
Add `CompatibleBranchDataItem` (#381)
alexweininger Sep 23, 2022
b26ecf8
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Oct 5, 2022
84674c8
Fixup
alexweininger Oct 5, 2022
d69a4ac
Remove `quickPickOptions`
bwateratmsft Oct 6, 2022
82a8e02
Make `pickAppResource` compatible with Tree API v2 (#382)
alexweininger Oct 6, 2022
fe7545a
Fix import
alexweininger Oct 12, 2022
efdcaf3
Workspace tree compatibility (#398)
alexweininger Oct 13, 2022
f539058
Expose `TreeDataProvider`s in API (#402)
alexweininger Oct 13, 2022
fafa95f
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Oct 13, 2022
14fc525
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Oct 13, 2022
02a386e
Stop registering V1 views
alexweininger Oct 13, 2022
22f9a24
Add "Create Resource" to view title
alexweininger Oct 14, 2022
ef91972
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Oct 15, 2022
96fb245
Add refresh capabilities to `CompatibleBranchDataProvider` (#406)
alexweininger Oct 18, 2022
3a4a4b5
refresh workspace
alexweininger Oct 19, 2022
b2c41c5
Fix duplicate resources
alexweininger Oct 19, 2022
dd0f916
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Oct 19, 2022
846bac2
Fixups
alexweininger Oct 19, 2022
84e0639
Change view Ids to match V1 (#408)
alexweininger Oct 19, 2022
4796fd6
Use `CompatibleAzExtTreeDataProvider` (#409)
alexweininger Oct 19, 2022
45820ec
Fix pick subscription
alexweininger Oct 19, 2022
94cf8d5
Fix type create commands
alexweininger Oct 19, 2022
99f353b
Cleanup unused extension variable
alexweininger Oct 19, 2022
82b3e7c
Remove unneeded void
alexweininger Nov 3, 2022
3ff193b
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Nov 9, 2022
bf6f6de
Improve errors in `CompatibleAzExtTreeDataProvider`
alexweininger Nov 10, 2022
6eed795
Reset unneeded changes
alexweininger Nov 10, 2022
91d89ee
Better rrganize compatibility source files
alexweininger Nov 10, 2022
5717bb8
Merge remote-tracking branch 'origin/api-v2' into bmw/philliphoff-res…
alexweininger Nov 10, 2022
725f52f
Improve types
alexweininger Nov 16, 2022
acc1978
Fix cast
alexweininger Nov 16, 2022
4867558
Add telemetry event for register application resource resolver
alexweininger Nov 16, 2022
7f4e321
Remove `_` prefix
alexweininger Nov 16, 2022
1c5ffab
Fix refresh command
alexweininger Nov 18, 2022
1a8f4c1
Fix removeChildFromCache
alexweininger Nov 18, 2022
5f7d85e
Pickup latest tools changes
alexweininger Nov 29, 2022
4cc2823
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
alexweininger Nov 29, 2022
ff0db98
Register azure tree
alexweininger Nov 30, 2022
eca2a4f
Cleanup tree registration
alexweininger Nov 30, 2022
866b1a5
Merge branch 'api-v2' into alex/api-v2-register-trees
alexweininger Nov 30, 2022
db482a2
Delete unused file
alexweininger Nov 30, 2022
8d89322
Fix option interface name
alexweininger Nov 30, 2022
c7f2f26
Call `refreshWorkspace`
alexweininger Nov 30, 2022
b57f8fa
Fixup
alexweininger Nov 30, 2022
6646d07
Merge branch 'alex/api-v2-register-trees' into bmw/philliphoff-resour…
alexweininger Nov 30, 2022
9b8ae75
Fixups
alexweininger Nov 30, 2022
0a0541f
Fixup
alexweininger Nov 30, 2022
9731eca
Don't expose EventEmitter
alexweininger Nov 30, 2022
fb898ec
Use AzExtResourceType
alexweininger Nov 30, 2022
e29a827
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
alexweininger Nov 30, 2022
1d1a95f
Fixup
alexweininger Nov 30, 2022
46f0560
Don't use tools
alexweininger Nov 30, 2022
aeac586
Update utils
alexweininger Nov 30, 2022
4c651d9
Remove fs-extra
alexweininger Nov 30, 2022
373f24b
Don't expose `ResourceGroupsItem` in api
alexweininger Nov 30, 2022
c9245bb
Use this instead of super
alexweininger Nov 30, 2022
1f13782
Revert changes to createResource.ts
alexweininger Nov 30, 2022
610676a
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
alexweininger Dec 1, 2022
5f08aea
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
alexweininger Dec 1, 2022
6dbec20
Update src/api/v2/compatibility/application/CompatibleApplicationReso…
alexweininger Dec 2, 2022
73da5d9
Combine disposables
alexweininger Dec 6, 2022
b2c992d
Combine disposables
alexweininger Dec 6, 2022
f0acea1
Update todo comment
alexweininger Dec 6, 2022
8024ea8
Remove reveal temporarily
alexweininger Dec 6, 2022
2ed6bd4
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
alexweininger Dec 6, 2022
84ec52b
Fixup refresh tree emitters
alexweininger Dec 6, 2022
253fd53
Add compat comment
alexweininger Dec 6, 2022
82e9391
Add comment
alexweininger Dec 6, 2022
0b5494d
Use common context value util
alexweininger Dec 6, 2022
29dd9f8
Fixup refresh workspace
alexweininger Dec 6, 2022
a217028
Fixup register resolver
alexweininger Dec 6, 2022
e5189f9
Make emitter private
alexweininger Dec 6, 2022
220ecef
Update comment
alexweininger Dec 6, 2022
dc172ce
Merge branch 'api-v2' into bmw/philliphoff-resource-api-compatshim
alexweininger Dec 6, 2022
b9588be
import types from published package
alexweininger Dec 6, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,8 @@
"@azure/arm-resources": "5.0.0",
"@azure/arm-resources-profile-2020-09-01-hybrid": "^2.0.0",
"@microsoft/vscode-azext-azureutils": "^0.3.4",
"@microsoft/vscode-azext-utils": "^0.3.14",
"@microsoft/vscode-azext-utils": "file:../vscode-azuretools/utils/microsoft-vscode-azext-utils-0.3.15.tgz",
nturinski marked this conversation as resolved.
Show resolved Hide resolved
"fs-extra": "^8.1.0",
"jsonc-parser": "^2.2.1",
"open": "^8.0.4",
"semver": "^7.3.7",
Expand Down
16 changes: 8 additions & 8 deletions src/api/AzureResourceGroupsExtensionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { Activity, AppResourceResolver, AzureHostExtensionApi, AzureResourceGrou
import { Disposable, TreeView } from 'vscode';

export class InternalAzureResourceGroupsExtensionApi implements AzureHostExtensionApi, AzureResourceGroupsExtensionApi {
public static apiVersion = '0.0.1';
public static apiVersion: '0.0.1' = '0.0.1';
alexweininger marked this conversation as resolved.
Show resolved Hide resolved

#appResourceTree: AzExtTreeDataProvider;
#appResourceTreeView: TreeView<AzExtTreeItem>;
#appResourceTreeView: TreeView<unknown>;
#workspaceResourceTree: AzExtTreeDataProvider;
#workspaceResourceTreeView: TreeView<AzExtTreeItem>;
#apiVersion: string;
#workspaceResourceTreeView: TreeView<unknown>;
#apiVersion: '0.0.1';
#revealTreeItem: (resourceId: string) => Promise<void>;
#registerApplicationResourceResolver: (id: string, resolver: AppResourceResolver) => Disposable;
#registerWorkspaceResourceProvider: (id: string, resolver: WorkspaceResourceProvider) => Disposable;
Expand All @@ -41,19 +41,19 @@ export class InternalAzureResourceGroupsExtensionApi implements AzureHostExtensi
return this.#appResourceTree;
}

public get appResourceTreeView(): TreeView<AzExtTreeItem> {
public get appResourceTreeView(): TreeView<unknown> {
bwateratmsft marked this conversation as resolved.
Show resolved Hide resolved
return this.#appResourceTreeView;
}

public get workspaceResourceTree(): AzExtTreeDataProvider {
return this.#workspaceResourceTree;
}

public get workspaceResourceTreeView(): TreeView<AzExtTreeItem> {
public get workspaceResourceTreeView(): TreeView<unknown> {
return this.#workspaceResourceTreeView;
}

public get apiVersion(): string {
public get apiVersion(): '0.0.1' {
return this.#apiVersion;
}

Expand Down Expand Up @@ -83,7 +83,7 @@ export class InternalAzureResourceGroupsExtensionApi implements AzureHostExtensi
return this.appResourceTree;
}

public get treeView(): TreeView<AzExtTreeItem> {
public get treeView(): TreeView<unknown> {
return this.appResourceTreeView;
}

Expand Down
41 changes: 33 additions & 8 deletions src/api/pickAppResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,43 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { AzExtTreeItem, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
import { AzExtResourceType, AzExtTreeItem, compatibilityPickAppResourceExperience, ContextValueFilter, getAzExtResourceType, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
import { PickAppResourceOptions } from "@microsoft/vscode-azext-utils/hostapi";
import { ext } from "../extensionVariables";
import { SubscriptionTreeItem } from "../tree/SubscriptionTreeItem";

export async function pickAppResource<T extends AzExtTreeItem>(context: ITreeItemPickerContext, options?: PickAppResourceOptions): Promise<T> {
const subscription: SubscriptionTreeItem = await ext.appResourceTree.showTreeItemPicker(SubscriptionTreeItem.contextValue, context);
const appResource = await subscription.pickAppResource(context, options);
return await compatibilityPickAppResourceExperience<T>(context, ext.v2.api.applicationResourceTreeDataProvider, {
nturinski marked this conversation as resolved.
Show resolved Hide resolved
resourceTypes: convertAppResourceFilterToAzExtResourceType(options?.filter),
childItemFilter: convertExpectedChildContextValueToContextValueFilter(options?.expectedChildContextValue)
});
}

function convertExpectedChildContextValueToContextValueFilter(expectedChildContextValue?: PickAppResourceOptions['expectedChildContextValue']): ContextValueFilter | undefined {
return expectedChildContextValue ? { include: expectedChildContextValue } : undefined
}

if (options?.expectedChildContextValue) {
return ext.appResourceTree.showTreeItemPicker(options.expectedChildContextValue, context, appResource);
} else {
return appResource as unknown as T;
function convertAppResourceFilterToAzExtResourceType(filter?: PickAppResourceOptions['filter']): AzExtResourceType[] | undefined {
if (!filter) {
return undefined;
}

filter = Array.isArray(filter) ? filter : [filter];

return filterMap(filter, getAzExtResourceType);
}

function filterMap<T, TMapped>(
source: T[],
predicateMapper: (item: T, index: number) => TMapped | null | undefined,
): TMapped[] {
let index = 0;
return source.reduce<TMapped[]>((accumulator, current) => {
const mapped = predicateMapper(current, index++);
// handles null or undefined
// eslint-disable-next-line eqeqeq
nturinski marked this conversation as resolved.
Show resolved Hide resolved
if (mapped != null) {
accumulator.push(mapped);
}
return accumulator;
}, []);
}
17 changes: 12 additions & 5 deletions src/api/registerApplicationResourceResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { AzExtResourceType, AzExtTreeItem } from "@microsoft/vscode-azext-utils";
import { AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi";
import { Disposable } from "vscode";
import { ext } from "../extensionVariables";
import { CompatibleApplicationResourceBranchDataProvider } from "./v2/compatibility/application/CompatibleApplicationResourceBranchDataProvider";
import { ApplicationResource, BranchDataProvider } from "./v2/v2AzureResourcesApi";

export const applicationResourceResolvers: Record<string, AppResourceResolver> = {};
alexweininger marked this conversation as resolved.
Show resolved Hide resolved

export function registerApplicationResourceResolver(id: string, resolver: AppResourceResolver): Disposable {
if (applicationResourceResolvers[id]) {
throw new Error(`Application resource resolver with id '${id}' has already been registered.`);
export function registerApplicationResourceResolver(type: AzExtResourceType, resolver: AppResourceResolver): Disposable {
if (applicationResourceResolvers[type]) {
throw new Error(`Application resource resolver with id '${type}' has already been registered.`);
}

applicationResourceResolvers[id] = resolver;
applicationResourceResolvers[type] = resolver;
ext.emitters.onDidRegisterResolver.fire(resolver);

const compat = new CompatibleApplicationResourceBranchDataProvider(resolver, 'azureResourceGroups.loadMore' /** TODO: what is the correct value for this? */);

ext.v2.api.registerApplicationResourceBranchDataProvider(type, compat as unknown as BranchDataProvider<ApplicationResource, AzExtTreeItem>);
alexweininger marked this conversation as resolved.
Show resolved Hide resolved

return new Disposable(() => {
delete applicationResourceResolvers[id];
delete applicationResourceResolvers[type];
});
}
16 changes: 12 additions & 4 deletions src/api/registerWorkspaceResourceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,31 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { callWithTelemetryAndErrorHandlingSync } from "@microsoft/vscode-azext-utils";
import { AzExtTreeItem, callWithTelemetryAndErrorHandlingSync } from "@microsoft/vscode-azext-utils";
import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi";
import { Disposable } from "vscode";
import { refreshWorkspace } from "../commands/workspace/refreshWorkspace";
import { ext } from "../extensionVariables";
import { CompatibilityWorkspaceResourceProvider } from "./v2/compatibility/workspace/CompatibilityWorkspaceResourceProvider";
import { CompatibleWorkspaceResourceBranchDataProvider } from "./v2/compatibility/workspace/CompatibleWorkspaceResourceBranchDataProvider";
import { BranchDataProvider, WorkspaceResource } from "./v2/v2AzureResourcesApi";

export const workspaceResourceProviders: Record<string, WorkspaceResourceProvider> = {};

export function registerWorkspaceResourceProvider(resourceType: string, provider: WorkspaceResourceProvider): Disposable {
workspaceResourceProviders[resourceType] = provider;

return callWithTelemetryAndErrorHandlingSync('registerWorkspaceResourceProvider', (context) => {
return callWithTelemetryAndErrorHandlingSync('registerWorkspaceResourceProvider', () => {
alexweininger marked this conversation as resolved.
Show resolved Hide resolved

void refreshWorkspace(context);
refreshWorkspace();

ext.v2.api.registerWorkspaceResourceProvider(new CompatibilityWorkspaceResourceProvider(resourceType, provider));
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
ext.v2.api.registerWorkspaceResourceBranchDataProvider(resourceType, new CompatibleWorkspaceResourceBranchDataProvider('azureWorkspace.loadMore') as unknown as BranchDataProvider<WorkspaceResource, AzExtTreeItem>)
bwateratmsft marked this conversation as resolved.
Show resolved Hide resolved

return new Disposable(() => {
delete workspaceResourceProviders[resourceType];
void refreshWorkspace(context);
refreshWorkspace();
nturinski marked this conversation as resolved.
Show resolved Hide resolved
bwateratmsft marked this conversation as resolved.
Show resolved Hide resolved
});
}) as Disposable;
}

114 changes: 114 additions & 0 deletions src/api/v2/compatibility/CompatibleAzExtTreeDataProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { AzExtParentTreeItem, AzExtTreeDataProvider, AzExtTreeItem, compatibilitySubscriptionExperience, contextValueExperience, findByIdExperience, IActionContext, IFindTreeItemContext, isWrapper, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
import { Disposable, Event, TreeItem, TreeView } from "vscode";
import { SubscriptionTreeItem } from "../../../tree/SubscriptionTreeItem";
import { ResourceGroupsItem } from "../../../tree/v2/ResourceGroupsItem";
import { ResourceTreeDataProviderBase } from "../../../tree/v2/ResourceTreeDataProviderBase";

/**
* An intermediate class that exists just to redeclare several events as abstract, so they
* can be re-redeclared as a accessors in {@link CompatibleAzExtTreeDataProvider} below
*/
abstract class IntermediateCompatibleAzExtTreeDataProvider extends AzExtTreeDataProvider {
public abstract onDidChangeTreeData: Event<AzExtTreeItem | undefined>;
public abstract onTreeItemCreate: Event<AzExtTreeItem>;
public abstract onDidExpandOrRefreshExpandedTreeItem: Event<AzExtTreeItem>;
}

export class CompatibleAzExtTreeDataProvider extends IntermediateCompatibleAzExtTreeDataProvider {
public constructor(private readonly tdp: ResourceTreeDataProviderBase) {
super({} as unknown as AzExtParentTreeItem, undefined as unknown as string);
}

public override getParent(treeItem: AzExtTreeItem): Promise<AzExtTreeItem | undefined> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.tdp.getParent(treeItem);
}

public override getTreeItem(treeItem: AzExtTreeItem): TreeItem {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.tdp.getTreeItem(treeItem);
}

public override getChildren(_treeItem?: AzExtParentTreeItem): Promise<AzExtTreeItem[]> {
alexweininger marked this conversation as resolved.
Show resolved Hide resolved
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.tdp.getChildren(_treeItem);
}

public override async findTreeItem<T>(fullId: string, context: IFindTreeItemContext): Promise<T | undefined> {
// Special handling for subscription tree item
// Use the new finder experience
// Unbox the item at the end

const result = await findByIdExperience(context, this.tdp, fullId);
return isWrapper(result) ? result.unwrap<T>() : result as unknown as T;
}

public override showTreeItemPicker<T>(expectedContextValues: string | RegExp | (string | RegExp)[], context: ITreeItemPickerContext & { canPickMany: true }, startingTreeItem?: AzExtTreeItem): Promise<T[]>;
public override async showTreeItemPicker<T>(expectedContextValues: string | RegExp | (string | RegExp)[], context: ITreeItemPickerContext, _startingTreeItem?: AzExtTreeItem): Promise<T> {
if (expectedContextValues === SubscriptionTreeItem.contextValue) {
const result = await compatibilitySubscriptionExperience(context, this.tdp);
const subscription = isWrapper(result) ? result.unwrap<T>() : result as unknown as T;
return { subscription } as unknown as T;
}

// TODO: support startingTreeItem

const result = await contextValueExperience(context, this.tdp, {
include: expectedContextValues,
});

return isWrapper(result) ? result.unwrap<T>() : result as unknown as T;
}

public override refresh(_context: IActionContext, treeItem?: AzExtTreeItem | undefined): Promise<void> {

// Flush the cache at and below the given treeItem
// Trigger a refresh at the given treeItem
this.tdp.onDidChangeTreeDataEmitter.fire(treeItem as unknown as ResourceGroupsItem);
alexweininger marked this conversation as resolved.
Show resolved Hide resolved

return Promise.resolve();
}

public override refreshUIOnly(treeItem: AzExtTreeItem | undefined): void {

this.tdp.onDidChangeTreeDataEmitter.fire(treeItem as unknown as ResourceGroupsItem);

}

public override loadMore(_treeItem: AzExtTreeItem, _context: IActionContext): Promise<void> {
// TODO: unknown how this will be implemented?
throw new Error('TODO: Implement this using the new load more approach');
}

//#region Things that should not be called
public override trackTreeItemCollapsibleState(_treeView: TreeView<AzExtTreeItem>): Disposable {
throw new ShouldNeverBeCalledError('trackTreeItemCollapsibleState method');
}

public get onDidChangeTreeData(): Event<AzExtTreeItem | undefined> {
throw new ShouldNeverBeCalledError('onDidChangeTreeData accessor');
}

public get onTreeItemCreate(): Event<AzExtTreeItem> {
throw new ShouldNeverBeCalledError('onTreeItemCreate accessor');
}

public get onDidExpandOrRefreshExpandedTreeItem(): Event<AzExtTreeItem> {
throw new ShouldNeverBeCalledError('onDidExpandOrRefreshExpandedTreeItem accessor');
}
//#endregion Things that should not be called
}

class ShouldNeverBeCalledError extends Error {
constructor(methodName: string) {
super(`${methodName} should never be called.`);
}
}
Loading