Add ExtensionDetails dialog and support install (#20845)

This commit is contained in:
christine betts
2026-03-10 17:12:47 -04:00
committed by GitHub
parent 519c75f410
commit 300929a32b
8 changed files with 512 additions and 44 deletions

View File

@@ -475,14 +475,18 @@ describe('extensionsCommand', () => {
mockInstallExtension.mockResolvedValue({ name: extension.url });
// Call onSelect
component.props.onSelect?.(extension);
await component.props.onSelect?.(extension);
await waitFor(() => {
expect(inferInstallMetadata).toHaveBeenCalledWith(extension.url);
expect(mockInstallExtension).toHaveBeenCalledWith({
source: extension.url,
type: 'git',
});
expect(mockInstallExtension).toHaveBeenCalledWith(
{
source: extension.url,
type: 'git',
},
undefined,
undefined,
);
});
expect(mockContext.ui.removeComponent).toHaveBeenCalledTimes(1);
@@ -622,10 +626,14 @@ describe('extensionsCommand', () => {
mockInstallExtension.mockResolvedValue({ name: packageName });
await installAction!(mockContext, packageName);
expect(inferInstallMetadata).toHaveBeenCalledWith(packageName);
expect(mockInstallExtension).toHaveBeenCalledWith({
source: packageName,
type: 'git',
});
expect(mockInstallExtension).toHaveBeenCalledWith(
{
source: packageName,
type: 'git',
},
undefined,
undefined,
);
expect(mockContext.ui.addItem).toHaveBeenCalledWith({
type: MessageType.INFO,
text: `Installing extension from "${packageName}"...`,
@@ -647,10 +655,14 @@ describe('extensionsCommand', () => {
await installAction!(mockContext, packageName);
expect(inferInstallMetadata).toHaveBeenCalledWith(packageName);
expect(mockInstallExtension).toHaveBeenCalledWith({
source: packageName,
type: 'git',
});
expect(mockInstallExtension).toHaveBeenCalledWith(
{
source: packageName,
type: 'git',
},
undefined,
undefined,
);
expect(mockContext.ui.addItem).toHaveBeenCalledWith({
type: MessageType.ERROR,
text: `Failed to install extension from "${packageName}": ${errorMessage}`,

View File

@@ -279,9 +279,9 @@ async function exploreAction(
return {
type: 'custom_dialog' as const,
component: React.createElement(ExtensionRegistryView, {
onSelect: (extension) => {
onSelect: async (extension, requestConsentOverride) => {
debugLogger.log(`Selected extension: ${extension.extensionName}`);
void installAction(context, extension.url);
await installAction(context, extension.url, requestConsentOverride);
context.ui.removeComponent();
},
onClose: () => context.ui.removeComponent(),
@@ -458,7 +458,11 @@ async function enableAction(context: CommandContext, args: string) {
}
}
async function installAction(context: CommandContext, args: string) {
async function installAction(
context: CommandContext,
args: string,
requestConsentOverride?: (consent: string) => Promise<boolean>,
) {
const extensionLoader = context.services.config?.getExtensionLoader();
if (!(extensionLoader instanceof ExtensionManager)) {
debugLogger.error(
@@ -505,8 +509,11 @@ async function installAction(context: CommandContext, args: string) {
try {
const installMetadata = await inferInstallMetadata(source);
const extension =
await extensionLoader.installOrUpdateExtension(installMetadata);
const extension = await extensionLoader.installOrUpdateExtension(
installMetadata,
undefined,
requestConsentOverride,
);
context.ui.addItem({
type: MessageType.INFO,
text: `Extension "${extension.name}" installed successfully.`,