From dd93e10bb4c83c0a66d717319c64ecc0d2365d81 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Tue, 17 Dec 2024 17:12:35 -0300 Subject: [PATCH 1/7] API for extending the connections pane --- src/positron-dts/positron.d.ts | 60 ++++++++++ .../browser/positron/mainThreadConnections.ts | 72 ++++++++++++ .../positron/extHost.positron.api.impl.ts | 10 ++ .../positron/extHost.positron.protocol.ts | 16 +++ .../api/common/positron/extHostConnections.ts | 90 +++++++++++++++ .../common/positron/extHostTypes.positron.ts | 6 + .../components/newConnectionModalDialog.tsx | 2 +- .../createConnectionState.tsx | 15 +-- .../listDriversState.tsx | 8 +- .../interfaces/positronConnectionsDriver.ts | 15 ++- .../browser/positronConnectionsDrivers.ts | 106 ++++++++++-------- 11 files changed, 336 insertions(+), 64 deletions(-) create mode 100644 src/vs/workbench/api/browser/positron/mainThreadConnections.ts create mode 100644 src/vs/workbench/api/common/positron/extHostConnections.ts diff --git a/src/positron-dts/positron.d.ts b/src/positron-dts/positron.d.ts index 861dca93303..be1b230a4fd 100644 --- a/src/positron-dts/positron.d.ts +++ b/src/positron-dts/positron.d.ts @@ -1101,6 +1101,59 @@ declare module 'positron' { pasteText(text: string): void; } + export enum ConnectionsInputType { + String = 'string', + Number = 'number', + Option = 'option', + } + + export interface ConnectionsInput { + // The unique identifier for the input. + id: string; + // A human-readable label for the input. + label: string; + // The type of the input. + type: ConnectionsInputType; + // Options, if the input type is an option. + options?: { 'identifier': string; 'title': string }[]; + // The default value for the input. + value?: string; + } + + export interface ConnectionsDriverMetadata { + // The language identifier for the driver. + // Drivers are grouped by language, not by runtime. + languageId: string; + // A human-readable name for the driver. + name: string; + // The base64-encoded SVG icon for the driver. + base64EncodedIconSvg?: string; + // The inputs required to create a connection. + // For instance, a connection might require a username + // and password. + inputs: Array; + } + + export interface ConnectionsDriver { + // The unique identifier for the driver. + driverId: string; + + // The metadata for the driver. + metadata: ConnectionsDriverMetadata; + + // Generates the connection code based on the inputs. + generateCode?: (inputs: Array) => string; + // Connect session + connect?: (code: string) => Promise; + // Checks if the dependencies for the driver are installed + // and functioning. + checkDependencies?: () => Promise; + // Installs the dependencies for the driver. + // For instance, R packages would install the required + // R packages, and or other dependencies. + installDependencies?: () => Promise; + } + namespace languages { /** * Register a statement range provider. @@ -1387,4 +1440,11 @@ declare module 'positron' { } + + /** + * Refers to methods related to the connections pane + */ + namespace connections { + export function registerConnectionDriver(driver: ConnectionsDriver): vscode.Disposable; + } } diff --git a/src/vs/workbench/api/browser/positron/mainThreadConnections.ts b/src/vs/workbench/api/browser/positron/mainThreadConnections.ts new file mode 100644 index 00000000000..7a00acab31d --- /dev/null +++ b/src/vs/workbench/api/browser/positron/mainThreadConnections.ts @@ -0,0 +1,72 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2023-2024 Posit Software, PBC. All rights reserved. + * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ + + +import { extHostNamedCustomer, IExtHostContext } from '../../../services/extensions/common/extHostCustomers'; +import { IDriver, IDriverMetadata, Input } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver'; +import { IPositronConnectionsService } from '../../../services/positronConnections/browser/interfaces/positronConnectionsService'; +import { ExtHostConnectionsShape, ExtHostPositronContext, MainPositronContext, MainThreadConnectionsShape } from '../../common/positron/extHost.positron.protocol'; + +@extHostNamedCustomer(MainPositronContext.MainThreadConnections) +export class MainThreadConnections implements MainThreadConnectionsShape { + private readonly _proxy: ExtHostConnectionsShape; + constructor( + extHostContext: IExtHostContext, + @IPositronConnectionsService private readonly _connectionsService: IPositronConnectionsService + ) { + this._proxy = extHostContext.getProxy(ExtHostPositronContext.ExtHostConnections); + } + + $registerConnectionDriver(driverId: string, metadata: IDriverMetadata, availableMethods: IAvailableDriverMethods): void { + this._connectionsService.driverManager.registerDriver(new MainThreadDriverAdapter( + driverId, metadata, availableMethods, this._proxy + )); + } + + $removeConnectionDriver(driverId: string): void { + this._connectionsService.driverManager.removeDriver(driverId); + } + + dispose(): void { + + } +} + +export interface IAvailableDriverMethods { + generateCode: boolean, + connect: boolean, + checkDependencies: boolean, + installDependencies: boolean +} + +class MainThreadDriverAdapter implements IDriver { + constructor( + readonly driverId: string, + readonly metadata: IDriverMetadata, + private readonly availableMethods: IAvailableDriverMethods, + private readonly _proxy: ExtHostConnectionsShape + ) { } + get generateCode() { + if (!this.availableMethods.generateCode) { + return undefined; + } + return (inputs: Input[]) => this._proxy.$driverGenerateCode(this.driverId, inputs); + } + get connect() { + if (!this.availableMethods.connect) { + return undefined; + } + } + get checkDependencies() { + if (!this.availableMethods.checkDependencies) { + return undefined; + } + } + get installDependencies() { + if (!this.availableMethods.installDependencies) { + return undefined; + } + } +} diff --git a/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts b/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts index a8313dee1bd..9840e3d9b46 100644 --- a/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts +++ b/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts @@ -29,6 +29,7 @@ import { ExtHostConsoleService } from './extHostConsoleService.js'; import { ExtHostMethods } from './extHostMethods.js'; import { ExtHostEditors } from '../extHostTextEditors.js'; import { UiFrontendRequest } from '../../../services/languageRuntime/common/positronUiComm.js'; +import { ExtHostConnections } from './extHostConnections.js'; /** * Factory interface for creating an instance of the Positron API. @@ -71,6 +72,7 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce const extHostMethods = rpcProtocol.set(ExtHostPositronContext.ExtHostMethods, new ExtHostMethods(rpcProtocol, extHostEditors, extHostDocuments, extHostModalDialogs, extHostLanguageRuntime, extHostWorkspace, extHostCommands, extHostContextKeyService)); + const extHostConnections = rpcProtocol.set(ExtHostPositronContext.ExtHostConnections, new ExtHostConnections(rpcProtocol)); return function (extension: IExtensionDescription, extensionInfo: IExtensionRegistries, configProvider: ExtHostConfigProvider): typeof positron { @@ -192,6 +194,12 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce }, }; + const connections: typeof positron.connections = { + registerConnectionDriver(driver: positron.ConnectionsDriver): vscode.Disposable { + return extHostConnections.registerConnectionDriver(driver); + } + }; + // --- End Positron --- return { @@ -201,6 +209,7 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce window, languages, methods, + connections, PositronOutputLocation: extHostTypes.PositronOutputLocation, RuntimeClientType: extHostTypes.RuntimeClientType, RuntimeClientState: extHostTypes.RuntimeClientState, @@ -216,6 +225,7 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce RuntimeOnlineState: extHostTypes.RuntimeOnlineState, RuntimeState: extHostTypes.RuntimeState, RuntimeCodeFragmentStatus: extHostTypes.RuntimeCodeFragmentStatus, + ConnectionsInputType: extHostTypes.ConnectionsInputType, }; }; } diff --git a/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts b/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts index 4cff48fba29..a8cbb3f1b6e 100644 --- a/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts +++ b/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts @@ -11,6 +11,8 @@ import { URI, UriComponents } from '../../../../base/common/uri.js'; import { IEditorContext } from '../../../services/frontendMethods/common/editorContext.js'; import { RuntimeClientType } from './extHostTypes.positron.js'; import { LanguageRuntimeDynState, RuntimeSessionMetadata } from 'positron'; +import { IDriverMetadata, Input } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { IAvailableDriverMethods } from '../../browser/positron/mainThreadConnections.js'; // NOTE: This check is really to ensure that extHost.protocol is included by the TypeScript compiler // as a dependency of this module, and therefore that it's initialized first. This is to avoid a @@ -107,6 +109,18 @@ export interface ExtHostMethodsShape { showQuestion(title: string, message: string, okButtonTitle: string, cancelButtonTitle: string): Promise; } +export interface MainThreadConnectionsShape { + $registerConnectionDriver(driverId: string, metadata: IDriverMetadata, availableMethods: IAvailableDriverMethods): void; + $removeConnectionDriver(driverId: string): void; +} + +export interface ExtHostConnectionsShape { + $driverGenerateCode(driverId: string, inputs: Input[]): Promise; + // $driverConnect(driverId: string, code: string): Promise; + // $driverCheckDependencies(driverId: string): Promise; + // $driverInstallDependencies(driverId: string): Promise; +} + /** * The view state of a preview in the Preview panel. Only one preview can be * active at a time (the one currently loaded into the panel); the active @@ -179,6 +193,7 @@ export const ExtHostPositronContext = { ExtHostConsoleService: createProxyIdentifier('ExtHostConsoleService'), ExtHostContextKeyService: createProxyIdentifier('ExtHostContextKeyService'), ExtHostMethods: createProxyIdentifier('ExtHostMethods'), + ExtHostConnections: createProxyIdentifier('ExtHostConnections'), }; export const MainPositronContext = { @@ -188,4 +203,5 @@ export const MainPositronContext = { MainThreadConsoleService: createProxyIdentifier('MainThreadConsoleService'), MainThreadContextKeyService: createProxyIdentifier('MainThreadContextKeyService'), MainThreadMethods: createProxyIdentifier('MainThreadMethods'), + MainThreadConnections: createProxyIdentifier('MainThreadConnections'), }; diff --git a/src/vs/workbench/api/common/positron/extHostConnections.ts b/src/vs/workbench/api/common/positron/extHostConnections.ts new file mode 100644 index 00000000000..84864ae9aa2 --- /dev/null +++ b/src/vs/workbench/api/common/positron/extHostConnections.ts @@ -0,0 +1,90 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2024 Posit Software, PBC. All rights reserved. + * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable } from 'vscode'; +import * as positron from 'positron'; +import * as extHostProtocol from './extHost.positron.protocol.js'; +import { Input, InputType } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; + +export class ExtHostConnections implements extHostProtocol.ExtHostConnectionsShape { + + private readonly _proxy: extHostProtocol.MainThreadConnectionsShape; + private _drivers: positron.ConnectionsDriver[] = []; + + constructor( + mainContext: extHostProtocol.IMainPositronContext, + ) { + // Trigger creation of the proxy + this._proxy = mainContext.getProxy(extHostProtocol.MainPositronContext.MainThreadConnections); + } + + public registerConnectionDriver(driver: positron.ConnectionsDriver): Disposable { + // Check if the driver is already registered, and if not push, otherwise replace + const existingDriverIndex = this._drivers.findIndex(d => d.driverId === driver.driverId); + if (existingDriverIndex !== -1) { + this._drivers[existingDriverIndex] = driver; + } else { + this._drivers.push(driver); + } + + const metadata = { + ...driver.metadata, + inputs: driver.metadata.inputs.map(i => extHost2MainThreadInput(i)) + } + + this._proxy.$registerConnectionDriver( + driver.driverId, + metadata, + { + generateCode: driver.generateCode ? true : false, + connect: driver.connect ? true : false, + checkDependencies: driver.checkDependencies ? true : false, + installDependencies: driver.installDependencies ? true : false + } + ); + return new Disposable(() => { }); + } + + public async $driverGenerateCode(driverId: string, inputs: Input[]) { + const driver = this._drivers.find(d => d.driverId === driverId); + if (!driver || !driver.generateCode) { + throw new Error(`Driver ${driverId} does not support code generation`); + } + return driver.generateCode(inputs.map( + i => ({ ...i, type: i.type as string as positron.ConnectionsInputType }) + )); + } + + public $driverConnect(driverId: string, code: string): Promise { + const driver = this._drivers.find(d => d.driverId === driverId); + if (!driver || !driver.connect) { + throw new Error(`Driver ${driverId} does not support connecting`); + } + return driver.connect(code); + } + + public $driverCheckDependencies(driverId: string): Promise { + const driver = this._drivers.find(d => d.driverId === driverId); + if (!driver || !driver.checkDependencies) { + throw new Error(`Driver ${driverId} does not support checking dependencies`); + } + return driver.checkDependencies(); + } + + public $driverInstallDependencies(driverId: string): Promise { + const driver = this._drivers.find(d => d.driverId === driverId); + if (!driver || !driver.installDependencies) { + throw new Error(`Driver ${driverId} does not support installing dependencies`); + } + return driver.installDependencies(); + } +} + +function extHost2MainThreadInput(input: positron.ConnectionsInput): Input { + return { + ...input, + type: input.type as string as InputType + } +} diff --git a/src/vs/workbench/api/common/positron/extHostTypes.positron.ts b/src/vs/workbench/api/common/positron/extHostTypes.positron.ts index a556393b5b8..ecdedd2771b 100644 --- a/src/vs/workbench/api/common/positron/extHostTypes.positron.ts +++ b/src/vs/workbench/api/common/positron/extHostTypes.positron.ts @@ -314,3 +314,9 @@ export enum LanguageRuntimeSessionLocation { */ Browser = 'browser', } + +export enum ConnectionsInputType { + String = 'string', + Number = 'number', + Option = 'option', +} diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx index 9bfad51005c..42799e3fb77 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx @@ -56,7 +56,7 @@ const NewConnectionModalDialog = (props: PropsWithChildren { // When hitting back, reset the language ID to the previously selected language id - setLanguageId(selectedDriver?.languageId); + setLanguageId(selectedDriver?.metadata.languageId); setSelectedDriver(undefined); }; diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx index d4bf60a2237..dff0f76dfea 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx @@ -30,18 +30,19 @@ interface CreateConnectionProps { export const CreateConnection = (props: PropsWithChildren) => { - const { name, languageId, generateCode } = props.selectedDriver; + const { generateCode, metadata } = props.selectedDriver; + const { name, languageId } = metadata; const { onBack, onCancel, services } = props; const editorRef = useRef(undefined!); - const [inputs, setInputs] = useState>(props.selectedDriver.inputs); - const [code, setCode] = useState(props.selectedDriver.generateCode?.(props.selectedDriver.inputs)); + const [inputs, setInputs] = useState>(metadata.inputs); + const [code, setCode] = useState(undefined); useEffect(() => { // Debounce the code generation to avoid unnecessary re-renders - const timeoutId = setTimeout(() => { + const timeoutId = setTimeout(async () => { if (generateCode) { - const code = generateCode(inputs); + const code = await generateCode(inputs); setCode(code); } }, 200); @@ -57,7 +58,7 @@ export const CreateConnection = (props: PropsWithChildren message: localize( 'positron.newConnectionModalDialog.createConnection.connecting', "Connecting to data source ({0})...", - props.selectedDriver.name + name ), severity: Severity.Info }); @@ -96,7 +97,7 @@ export const CreateConnection = (props: PropsWithChildren -
+
{(() => localize('positron.newConnectionModalDialog.createConnection.code', "Connection Code"))()} diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx index 6d2f300be12..8b97696d8ba 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx @@ -36,7 +36,7 @@ export const ListDrivers = (props: PropsWithChildren) => { const driverManager = props.services.connectionsService.driverManager; const drivers = languageId ? - driverManager.getDrivers().filter(driver => driver.languageId === languageId) : + driverManager.getDrivers().filter(driver => driver.metadata.languageId === languageId) : []; const onLanguageChangeHandler = (lang: string) => { @@ -79,15 +79,15 @@ export const ListDrivers = (props: PropsWithChildren) => { { drivers.length > 0 ? drivers.map(driver => { - const icon = driver.base64EncodedIconSvg ? - : + const icon = driver.metadata.base64EncodedIconSvg ? + :
; return
{icon}
onDriverSelectedHandler(driver)}>
- {driver.name} + {driver.metadata.name}
diff --git a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsDriver.ts b/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsDriver.ts index 2fee6d820d8..7ca100bd9d9 100644 --- a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsDriver.ts +++ b/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsDriver.ts @@ -22,9 +22,7 @@ export interface Input { value?: string; } -export interface IDriver { - // The unique identifier for the driver. - driverId: string; +export interface IDriverMetadata { // The language identifier for the driver. // Drivers are grouped by language, not by runtime. languageId: string; @@ -36,8 +34,17 @@ export interface IDriver { // For instance, a connection might require a username // and password. inputs: Array; +} + +export interface IDriver { + // The unique identifier for the driver. + driverId: string; + + // The metadata for the driver. + metadata: IDriverMetadata; + // Generates the connection code based on the inputs. - generateCode?: (inputs: Array) => string; + generateCode?: (inputs: Array) => Promise; // Connect session connect?: (code: string) => Promise; // Checks if the dependencies for the driver are installed diff --git a/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts b/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts index ac5e78c12c3..19f3c086cab 100644 --- a/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts +++ b/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { RuntimeCodeExecutionMode, RuntimeErrorBehavior } from '../../languageRuntime/common/languageRuntimeService.js'; -import { IDriver, Input, InputType } from './interfaces/positronConnectionsDriver.js'; +import { IDriver, IDriverMetadata, Input, InputType } from './interfaces/positronConnectionsDriver.js'; import { IPositronConnectionsService } from './interfaces/positronConnectionsService.js'; import { ILanguageRuntimeSession } from '../../runtimeSession/common/runtimeSessionService.js'; @@ -25,6 +25,13 @@ export class PositronConnectionsDriverManager { } } + removeDriver(driverId: string): void { + const index = this.drivers.findIndex(d => d.driverId === driverId); + if (index > 0) { + this.drivers.splice(index, 1); + } + } + getDrivers(): IDriver[] { return this.drivers; } @@ -38,55 +45,58 @@ export class PositronConnectionsDriverManager { class RPostgreSQLDriver implements IDriver { constructor(readonly service: IPositronConnectionsService) { } - languageId: string = 'r'; driverId: string = 'postgres'; - name: string = 'PostgresSQL'; - inputs: Input[] = [ - { - 'id': 'dbname', - 'label': 'Database Name', - 'type': InputType.String, - 'value': 'localhost' - }, - { - 'id': 'host', - 'label': 'Host', - 'type': InputType.String, - 'value': 'localhost' - }, - { - 'id': 'port', - 'label': 'Port', - 'type': InputType.Number, - 'value': '5432' - }, - { - 'id': 'user', - 'label': 'User', - 'type': InputType.String, - 'value': 'postgres' - }, - { - 'id': 'password', - 'label': 'Password', - 'type': InputType.String, - 'value': 'password' - }, - { - 'id': 'bigint', - 'label': 'Integer representation', - 'type': InputType.Option, - 'options': [ - { 'identifier': 'integer64', 'title': 'integer64' }, - { 'identifier': 'integer', 'title': 'integer' }, - { 'identifier': 'numeric', 'title': 'numeric' }, - { 'identifier': 'character', 'title': 'character' } - ], - 'value': 'integer64' - } - ]; - generateCode(inputs: Array) { + metadata: IDriverMetadata = { + languageId: 'r', + name: 'PostgresSQL', + inputs: [ + { + 'id': 'dbname', + 'label': 'Database Name', + 'type': InputType.String, + 'value': 'localhost' + }, + { + 'id': 'host', + 'label': 'Host', + 'type': InputType.String, + 'value': 'localhost' + }, + { + 'id': 'port', + 'label': 'Port', + 'type': InputType.Number, + 'value': '5432' + }, + { + 'id': 'user', + 'label': 'User', + 'type': InputType.String, + 'value': 'postgres' + }, + { + 'id': 'password', + 'label': 'Password', + 'type': InputType.String, + 'value': 'password' + }, + { + 'id': 'bigint', + 'label': 'Integer representation', + 'type': InputType.Option, + 'options': [ + { 'identifier': 'integer64', 'title': 'integer64' }, + { 'identifier': 'integer', 'title': 'integer' }, + { 'identifier': 'numeric', 'title': 'numeric' }, + { 'identifier': 'character', 'title': 'character' } + ], + 'value': 'integer64' + } + ] + } + + async generateCode(inputs: Array) { const dbname = inputs.find(input => input.id === 'dbname')?.value; const host = inputs.find(input => input.id === 'host')?.value; const port = inputs.find(input => input.id === 'port')?.value; From f2cb107d6756d7eb52ce37b7a3e93bbf88fdacf7 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 18 Dec 2024 09:16:42 -0300 Subject: [PATCH 2/7] Simplify types by removing the enum defn --- src/positron-dts/positron.d.ts | 8 +---- .../positron/extHost.positron.api.impl.ts | 1 - .../positron/extHost.positron.protocol.ts | 6 ++-- .../api/common/positron/extHostConnections.ts | 34 ++++++------------- .../common/positron/extHostTypes.positron.ts | 6 ---- .../createConnectionState.tsx | 8 ++--- .../interfaces/positronConnectionsDriver.ts | 8 +---- .../browser/positronConnectionsDrivers.ts | 14 ++++---- 8 files changed, 26 insertions(+), 59 deletions(-) diff --git a/src/positron-dts/positron.d.ts b/src/positron-dts/positron.d.ts index be1b230a4fd..1c56a155ffa 100644 --- a/src/positron-dts/positron.d.ts +++ b/src/positron-dts/positron.d.ts @@ -1101,19 +1101,13 @@ declare module 'positron' { pasteText(text: string): void; } - export enum ConnectionsInputType { - String = 'string', - Number = 'number', - Option = 'option', - } - export interface ConnectionsInput { // The unique identifier for the input. id: string; // A human-readable label for the input. label: string; // The type of the input. - type: ConnectionsInputType; + type: 'string' | 'number' | 'option'; // Options, if the input type is an option. options?: { 'identifier': string; 'title': string }[]; // The default value for the input. diff --git a/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts b/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts index 9840e3d9b46..f21dc1256d2 100644 --- a/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts +++ b/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts @@ -225,7 +225,6 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce RuntimeOnlineState: extHostTypes.RuntimeOnlineState, RuntimeState: extHostTypes.RuntimeState, RuntimeCodeFragmentStatus: extHostTypes.RuntimeCodeFragmentStatus, - ConnectionsInputType: extHostTypes.ConnectionsInputType, }; }; } diff --git a/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts b/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts index a8cbb3f1b6e..20c9601e2da 100644 --- a/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts +++ b/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts @@ -116,9 +116,9 @@ export interface MainThreadConnectionsShape { export interface ExtHostConnectionsShape { $driverGenerateCode(driverId: string, inputs: Input[]): Promise; - // $driverConnect(driverId: string, code: string): Promise; - // $driverCheckDependencies(driverId: string): Promise; - // $driverInstallDependencies(driverId: string): Promise; + $driverConnect(driverId: string, code: string): Promise; + $driverCheckDependencies(driverId: string): Promise; + $driverInstallDependencies(driverId: string): Promise; } /** diff --git a/src/vs/workbench/api/common/positron/extHostConnections.ts b/src/vs/workbench/api/common/positron/extHostConnections.ts index 84864ae9aa2..ad1178bf16d 100644 --- a/src/vs/workbench/api/common/positron/extHostConnections.ts +++ b/src/vs/workbench/api/common/positron/extHostConnections.ts @@ -3,10 +3,10 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vscode'; import * as positron from 'positron'; import * as extHostProtocol from './extHost.positron.protocol.js'; -import { Input, InputType } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { Input } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { Disposable } from '../extHostTypes.js'; export class ExtHostConnections implements extHostProtocol.ExtHostConnectionsShape { @@ -29,14 +29,9 @@ export class ExtHostConnections implements extHostProtocol.ExtHostConnectionsSha this._drivers.push(driver); } - const metadata = { - ...driver.metadata, - inputs: driver.metadata.inputs.map(i => extHost2MainThreadInput(i)) - } - this._proxy.$registerConnectionDriver( driver.driverId, - metadata, + driver.metadata, { generateCode: driver.generateCode ? true : false, connect: driver.connect ? true : false, @@ -52,39 +47,30 @@ export class ExtHostConnections implements extHostProtocol.ExtHostConnectionsSha if (!driver || !driver.generateCode) { throw new Error(`Driver ${driverId} does not support code generation`); } - return driver.generateCode(inputs.map( - i => ({ ...i, type: i.type as string as positron.ConnectionsInputType }) - )); + return driver.generateCode(inputs); } - public $driverConnect(driverId: string, code: string): Promise { + public async $driverConnect(driverId: string, code: string): Promise { const driver = this._drivers.find(d => d.driverId === driverId); if (!driver || !driver.connect) { throw new Error(`Driver ${driverId} does not support connecting`); } - return driver.connect(code); + return await driver.connect(code); } - public $driverCheckDependencies(driverId: string): Promise { + public async $driverCheckDependencies(driverId: string): Promise { const driver = this._drivers.find(d => d.driverId === driverId); if (!driver || !driver.checkDependencies) { throw new Error(`Driver ${driverId} does not support checking dependencies`); } - return driver.checkDependencies(); + return await driver.checkDependencies(); } - public $driverInstallDependencies(driverId: string): Promise { + public async $driverInstallDependencies(driverId: string): Promise { const driver = this._drivers.find(d => d.driverId === driverId); if (!driver || !driver.installDependencies) { throw new Error(`Driver ${driverId} does not support installing dependencies`); } - return driver.installDependencies(); - } -} - -function extHost2MainThreadInput(input: positron.ConnectionsInput): Input { - return { - ...input, - type: input.type as string as InputType + return await driver.installDependencies(); } } diff --git a/src/vs/workbench/api/common/positron/extHostTypes.positron.ts b/src/vs/workbench/api/common/positron/extHostTypes.positron.ts index ecdedd2771b..a556393b5b8 100644 --- a/src/vs/workbench/api/common/positron/extHostTypes.positron.ts +++ b/src/vs/workbench/api/common/positron/extHostTypes.positron.ts @@ -314,9 +314,3 @@ export enum LanguageRuntimeSessionLocation { */ Browser = 'browser', } - -export enum ConnectionsInputType { - String = 'string', - Number = 'number', - Option = 'option', -} diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx index dff0f76dfea..4134f96765d 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx @@ -15,7 +15,7 @@ import { localize } from '../../../../../../nls.js'; import { PositronConnectionsServices } from '../../positronConnectionsContext.js'; import { SimpleCodeEditor, SimpleCodeEditorWidget } from '../simpleCodeEditor.js'; import Severity from '../../../../../../base/common/severity.js'; -import { IDriver, Input, InputType } from '../../../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { IDriver, Input } from '../../../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; import { LabeledTextInput } from '../../../../../browser/positronComponents/positronModalDialog/components/labeledTextInput.js'; import { RadioGroup } from '../../../../../browser/positronComponents/positronModalDialog/components/radioGroup.js'; import { PositronModalReactRenderer } from '../../../../../browser/positronModalReactRenderer/positronModalReactRenderer.js'; @@ -179,7 +179,7 @@ const FormElement = (props: PropsWithChildren) => { const { label, value: defaultValue = '', type, options } = props.input; switch (type) { - case InputType.Number: + case 'number': return
) => { onChange={(e) => props.onChange(e.target.value)} >
; - case InputType.Option: + case 'option': return
; - case InputType.String: + case 'string': default: return
Date: Wed, 18 Dec 2024 13:37:44 -0300 Subject: [PATCH 3/7] Move driver definition to extension + allow executing methods --- extensions/positron-r/src/connections.ts | 99 +++++++++++++++ extensions/positron-r/src/extension.ts | 4 + .../api/browser/extensionHost.contribution.ts | 1 + .../browser/positron/mainThreadConnections.ts | 12 +- .../positron/mainThreadLanguageRuntime.ts | 2 +- .../positron/extHost.positron.protocol.ts | 2 +- .../api/common/positron/extHostConnections.ts | 2 +- .../browser/components/listConnections.tsx | 2 +- .../components/newConnectionModalDialog.tsx | 2 +- .../createConnectionState.tsx | 2 +- .../listDriversState.tsx | 2 +- .../browser/components/schemaNavigation.tsx | 2 +- .../positronConnections.contribution.ts | 2 +- .../browser/positronConnectionsContext.tsx | 2 +- .../browser/positronConnectionsView.tsx | 2 +- .../browser/positronConnectionsDrivers.ts | 120 +----------------- .../browser/positronConnectionsInstance.ts | 6 +- .../browser/positronConnectionsService.ts | 4 +- .../browser/positronConnectionsUtils.ts | 21 +-- .../interfaces/positronConnectionsDriver.ts | 0 .../interfaces/positronConnectionsInstance.ts | 18 ++- .../interfaces/positronConnectionsService.ts | 2 +- 22 files changed, 151 insertions(+), 158 deletions(-) create mode 100644 extensions/positron-r/src/connections.ts rename src/vs/workbench/services/positronConnections/{browser => common}/interfaces/positronConnectionsDriver.ts (100%) rename src/vs/workbench/services/positronConnections/{browser => common}/interfaces/positronConnectionsInstance.ts (84%) rename src/vs/workbench/services/positronConnections/{browser => common}/interfaces/positronConnectionsService.ts (95%) diff --git a/extensions/positron-r/src/connections.ts b/extensions/positron-r/src/connections.ts new file mode 100644 index 00000000000..bc78542c959 --- /dev/null +++ b/extensions/positron-r/src/connections.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2023-2024 Posit Software, PBC. All rights reserved. + * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as positron from 'positron'; + +export function registerConnectionDrivers() { + positron.connections.registerConnectionDriver(new RPostgreSQLDriver()); +} + +class RPostgreSQLDriver implements positron.ConnectionsDriver { + driverId: string = 'postgres'; + metadata: positron.ConnectionsDriverMetadata = { + languageId: 'r', + name: 'PostgresSQL', + inputs: [ + { + 'id': 'dbname', + 'label': 'Database Name', + 'type': 'string', + 'value': 'localhost' + }, + { + 'id': 'host', + 'label': 'Host', + 'type': 'string', + 'value': 'localhost' + }, + { + 'id': 'port', + 'label': 'Port', + 'type': 'number', + 'value': '5432' + }, + { + 'id': 'user', + 'label': 'User', + 'type': 'string', + 'value': 'postgres' + }, + { + 'id': 'password', + 'label': 'Password', + 'type': 'string', + 'value': 'password' + }, + { + 'id': 'bigint', + 'label': 'Integer representation', + 'type': 'option', + 'options': [ + { 'identifier': 'integer64', 'title': 'integer64' }, + { 'identifier': 'integer', 'title': 'integer' }, + { 'identifier': 'numeric', 'title': 'numeric' }, + { 'identifier': 'character', 'title': 'character' } + ], + 'value': 'integer64' + } + ] + }; + + generateCode(inputs: positron.ConnectionsInput[]) { + const dbname = inputs.find(input => input.id === 'dbname')?.value; + const host = inputs.find(input => input.id === 'host')?.value; + const port = inputs.find(input => input.id === 'port')?.value; + const user = inputs.find(input => input.id === 'user')?.value; + const password = inputs.find(input => input.id === 'password')?.value; + const bigint = inputs.find(input => input.id === 'bigint')?.value; + + return `library(DBI) +con <- dbConnect( + RPostgres::Postgres(), + dbname = '${dbname ?? ''}', + host = '${host ?? ''}', + port = ${port ?? ''}, + user = '${user ?? ''}', + password = '${password ?? ''}', + bigint = '${bigint ?? ''}' +) +`; + } + + async connect(code: string) { + const exec = await positron.runtime.executeCode( + 'r', + code, + true, + false, + positron.RuntimeCodeExecutionMode.Interactive, + positron.RuntimeErrorBehavior.Continue + ); + if (!exec) { + throw new Error('Failed to execute code'); + } + return; + } +} + diff --git a/extensions/positron-r/src/extension.ts b/extensions/positron-r/src/extension.ts index 26963c07caf..79ddf5755d5 100644 --- a/extensions/positron-r/src/extension.ts +++ b/extensions/positron-r/src/extension.ts @@ -13,6 +13,7 @@ import { setContexts } from './contexts'; import { setupTestExplorer, refreshTestExplorer } from './testing/testing'; import { RRuntimeManager } from './runtime-manager'; import { registerUriHandler } from './uri-handler'; +import { registerConnectionDrivers } from './connections'; export const LOGGER = vscode.window.createOutputChannel('Positron R Extension', { log: true }); @@ -47,4 +48,7 @@ export function activate(context: vscode.ExtensionContext) { refreshTestExplorer(context); } }); + + // Register connection drivers. + registerConnectionDrivers(); } diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index 2bdfb3da6e9..eb1d814042c 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -96,6 +96,7 @@ import './positron/mainThreadPreviewPanel.js'; import './positron/mainThreadModalDialogs.js'; import './positron/mainThreadConsoleService.js'; import './positron/mainThreadContextKeyService.js'; +import './positron/mainThreadConnections.js'; // --- End Positron --- export class ExtensionPoints implements IWorkbenchContribution { diff --git a/src/vs/workbench/api/browser/positron/mainThreadConnections.ts b/src/vs/workbench/api/browser/positron/mainThreadConnections.ts index 7a00acab31d..a217e359a99 100644 --- a/src/vs/workbench/api/browser/positron/mainThreadConnections.ts +++ b/src/vs/workbench/api/browser/positron/mainThreadConnections.ts @@ -3,11 +3,10 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ - -import { extHostNamedCustomer, IExtHostContext } from '../../../services/extensions/common/extHostCustomers'; -import { IDriver, IDriverMetadata, Input } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver'; -import { IPositronConnectionsService } from '../../../services/positronConnections/browser/interfaces/positronConnectionsService'; -import { ExtHostConnectionsShape, ExtHostPositronContext, MainPositronContext, MainThreadConnectionsShape } from '../../common/positron/extHost.positron.protocol'; +import { ExtHostConnectionsShape, ExtHostPositronContext, MainPositronContext, MainThreadConnectionsShape } from '../../common/positron/extHost.positron.protocol.js'; +import { extHostNamedCustomer, IExtHostContext } from '../../../services/extensions/common/extHostCustomers.js'; +import { IDriver, IDriverMetadata, Input } from '../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; +import { IPositronConnectionsService } from '../../../services/positronConnections/common/interfaces/positronConnectionsService.js'; @extHostNamedCustomer(MainPositronContext.MainThreadConnections) export class MainThreadConnections implements MainThreadConnectionsShape { @@ -58,15 +57,18 @@ class MainThreadDriverAdapter implements IDriver { if (!this.availableMethods.connect) { return undefined; } + return (code: string) => this._proxy.$driverConnect(this.driverId, code); } get checkDependencies() { if (!this.availableMethods.checkDependencies) { return undefined; } + return () => this._proxy.$driverCheckDependencies(this.driverId); } get installDependencies() { if (!this.availableMethods.installDependencies) { return undefined; } + return () => this._proxy.$driverInstallDependencies(this.driverId); } } diff --git a/src/vs/workbench/api/browser/positron/mainThreadLanguageRuntime.ts b/src/vs/workbench/api/browser/positron/mainThreadLanguageRuntime.ts index 9df3b01be99..49ca0cac2e0 100644 --- a/src/vs/workbench/api/browser/positron/mainThreadLanguageRuntime.ts +++ b/src/vs/workbench/api/browser/positron/mainThreadLanguageRuntime.ts @@ -40,7 +40,7 @@ import { IRuntimeStartupService, RuntimeStartupPhase } from '../../../services/r import { SerializableObjectWithBuffers } from '../../../services/extensions/common/proxyIdentifier.js'; import { isWebviewReplayMessage } from '../../../contrib/positronWebviewPreloads/browser/utils.js'; import { IPositronWebviewPreloadService } from '../../../services/positronWebviewPreloads/browser/positronWebviewPreloadService.js'; -import { IPositronConnectionsService } from '../../../services/positronConnections/browser/interfaces/positronConnectionsService.js'; +import { IPositronConnectionsService } from '../../../services/positronConnections/common/interfaces/positronConnectionsService.js'; /** * Represents a language runtime event (for example a message or state change) diff --git a/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts b/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts index 20c9601e2da..5a5d72593da 100644 --- a/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts +++ b/src/vs/workbench/api/common/positron/extHost.positron.protocol.ts @@ -11,7 +11,7 @@ import { URI, UriComponents } from '../../../../base/common/uri.js'; import { IEditorContext } from '../../../services/frontendMethods/common/editorContext.js'; import { RuntimeClientType } from './extHostTypes.positron.js'; import { LanguageRuntimeDynState, RuntimeSessionMetadata } from 'positron'; -import { IDriverMetadata, Input } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { IDriverMetadata, Input } from '../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; import { IAvailableDriverMethods } from '../../browser/positron/mainThreadConnections.js'; // NOTE: This check is really to ensure that extHost.protocol is included by the TypeScript compiler diff --git a/src/vs/workbench/api/common/positron/extHostConnections.ts b/src/vs/workbench/api/common/positron/extHostConnections.ts index ad1178bf16d..a2d2a64501d 100644 --- a/src/vs/workbench/api/common/positron/extHostConnections.ts +++ b/src/vs/workbench/api/common/positron/extHostConnections.ts @@ -5,7 +5,7 @@ import * as positron from 'positron'; import * as extHostProtocol from './extHost.positron.protocol.js'; -import { Input } from '../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { Input } from '../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; import { Disposable } from '../extHostTypes.js'; export class ExtHostConnections implements extHostProtocol.ExtHostConnectionsShape { diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/listConnections.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/listConnections.tsx index 27d1ccef7d4..68c4821e8ac 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/listConnections.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/listConnections.tsx @@ -21,7 +21,7 @@ import { PositronConnectionsServices, usePositronConnectionsContext } from '../p import { FixedSizeList as List } from 'react-window'; import { positronClassNames } from '../../../../../base/common/positronUtilities.js'; import { languageIdToName } from './schemaNavigation.js'; -import { IPositronConnectionInstance } from '../../../../services/positronConnections/browser/interfaces/positronConnectionsInstance.js'; +import { IPositronConnectionInstance } from '../../../../services/positronConnections/common/interfaces/positronConnectionsInstance.js'; import { DisposableStore } from '../../../../../base/common/lifecycle.js'; import { showResumeConnectionModalDialog } from './resumeConnectionModalDialog.js'; import { localize } from '../../../../../nls.js'; diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx index 42799e3fb77..64652efbcbe 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog.tsx @@ -18,7 +18,7 @@ import { PositronConnectionsServices } from '../positronConnectionsContext.js'; import { ContentArea } from '../../../../browser/positronComponents/positronModalDialog/components/contentArea.js'; import { CreateConnection } from './newConnectionModalDialog/createConnectionState.js'; import { ListDrivers } from './newConnectionModalDialog/listDriversState.js'; -import { IDriver } from '../../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { IDriver } from '../../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; const NEW_CONNECTION_MODAL_DIALOG_WIDTH = 700; const NEW_CONNECTION_MODAL_DIALOG_HEIGHT = 630; diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx index 4134f96765d..3d5331af445 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/createConnectionState.tsx @@ -15,7 +15,7 @@ import { localize } from '../../../../../../nls.js'; import { PositronConnectionsServices } from '../../positronConnectionsContext.js'; import { SimpleCodeEditor, SimpleCodeEditorWidget } from '../simpleCodeEditor.js'; import Severity from '../../../../../../base/common/severity.js'; -import { IDriver, Input } from '../../../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { IDriver, Input } from '../../../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; import { LabeledTextInput } from '../../../../../browser/positronComponents/positronModalDialog/components/labeledTextInput.js'; import { RadioGroup } from '../../../../../browser/positronComponents/positronModalDialog/components/radioGroup.js'; import { PositronModalReactRenderer } from '../../../../../browser/positronModalReactRenderer/positronModalReactRenderer.js'; diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx index 8b97696d8ba..d40e9a81fc8 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/newConnectionModalDialog/listDriversState.tsx @@ -16,7 +16,7 @@ import { PositronConnectionsServices } from '../../positronConnectionsContext.js import { LanguageRuntimeMetadata } from 'positron'; import { DropDownListBox } from '../../../../../browser/positronComponents/dropDownListBox/dropDownListBox.js'; import { DropDownListBoxItem } from '../../../../../browser/positronComponents/dropDownListBox/dropDownListBoxItem.js'; -import { IDriver } from '../../../../../services/positronConnections/browser/interfaces/positronConnectionsDriver.js'; +import { IDriver } from '../../../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; interface ListDriversProps { readonly services: PositronConnectionsServices; diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/schemaNavigation.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/schemaNavigation.tsx index 8be625fab09..5be6b92f5db 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/schemaNavigation.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/schemaNavigation.tsx @@ -8,7 +8,6 @@ import { useStateRef } from '../../../../../base/browser/ui/react/useStateRef.js import { DisposableStore } from '../../../../../base/common/lifecycle.js'; import { usePositronConnectionsContext } from '../positronConnectionsContext.js'; import * as DOM from '../../../../../base/browser/dom.js'; -import { IPositronConnectionEntry } from '../../../../services/positronConnections/browser/positronConnectionsUtils.js'; import { ActionBar, ACTION_BAR_HEIGHT } from './schemaNavigationActionBar.js'; import { FixedSizeList as List } from 'react-window'; import { positronClassNames } from '../../../../../base/common/positronUtilities.js'; @@ -16,6 +15,7 @@ import './schemaNavigation.css'; import { ViewsProps } from '../positronConnections.js'; import Severity from '../../../../../base/common/severity.js'; import { localize } from '../../../../../nls.js'; +import { IPositronConnectionEntry } from '../../../../services/positronConnections/common/interfaces/positronConnectionsInstance.js'; export interface SchemaNavigationProps extends ViewsProps { } diff --git a/src/vs/workbench/contrib/positronConnections/browser/positronConnections.contribution.ts b/src/vs/workbench/contrib/positronConnections/browser/positronConnections.contribution.ts index 47027028499..cd9d9e58cbe 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/positronConnections.contribution.ts +++ b/src/vs/workbench/contrib/positronConnections/browser/positronConnections.contribution.ts @@ -8,7 +8,7 @@ import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js' import * as nls from '../../../../nls.js'; import { Registry } from '../../../../platform/registry/common/platform.js'; import { Extensions, IViewContainersRegistry, IViewsRegistry, ViewContainerLocation } from '../../../common/views.js'; -import { POSITRON_CONNECTIONS_VIEW_ID } from '../../../services/positronConnections/browser/interfaces/positronConnectionsService.js'; +import { POSITRON_CONNECTIONS_VIEW_ID } from '../../../services/positronConnections/common/interfaces/positronConnectionsService.js'; import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js'; import { ViewPaneContainer } from '../../../browser/parts/views/viewPaneContainer.js'; import { PositronConnectionsView } from './positronConnectionsView.js'; diff --git a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx index 0b2274e652d..8c7f196d705 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx @@ -22,7 +22,7 @@ import { ILayoutService } from '../../../../platform/layout/browser/layoutServic import { INotificationService } from '../../../../platform/notification/common/notification.js'; import { IEditorService } from '../../../services/editor/common/editorService.js'; import { ILanguageRuntimeService } from '../../../services/languageRuntime/common/languageRuntimeService.js'; -import { IPositronConnectionsService } from '../../../services/positronConnections/browser/interfaces/positronConnectionsService.js'; +import { IPositronConnectionsService } from '../../../services/positronConnections/common/interfaces/positronConnectionsService.js'; import { IRuntimeSessionService } from '../../../services/runtimeSession/common/runtimeSessionService.js'; import { IRuntimeStartupService } from '../../../services/runtimeStartup/common/runtimeStartupService.js'; diff --git a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx index 66c4030c7cd..ac7289376a6 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx @@ -21,7 +21,7 @@ import * as DOM from '../../../../base/browser/dom.js'; import { PositronConnections } from './positronConnections.js'; import * as React from 'react'; import { ICommandService } from '../../../../platform/commands/common/commands.js'; -import { IPositronConnectionsService } from '../../../services/positronConnections/browser/interfaces/positronConnectionsService.js'; +import { IPositronConnectionsService } from '../../../services/positronConnections/common/interfaces/positronConnectionsService.js'; import { ILayoutService } from '../../../../platform/layout/browser/layoutService.js'; import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js'; import { INotificationService } from '../../../../platform/notification/common/notification.js'; diff --git a/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts b/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts index 73d5d9de289..d6a81999ffa 100644 --- a/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts +++ b/src/vs/workbench/services/positronConnections/browser/positronConnectionsDrivers.ts @@ -3,17 +3,13 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ -import { RuntimeCodeExecutionMode, RuntimeErrorBehavior } from '../../languageRuntime/common/languageRuntimeService.js'; -import { IDriver, IDriverMetadata, Input } from './interfaces/positronConnectionsDriver.js'; -import { IPositronConnectionsService } from './interfaces/positronConnectionsService.js'; -import { ILanguageRuntimeSession } from '../../runtimeSession/common/runtimeSessionService.js'; +import { IDriver } from '../common/interfaces/positronConnectionsDriver.js'; +import { IPositronConnectionsService } from '../common/interfaces/positronConnectionsService.js'; export class PositronConnectionsDriverManager { private readonly drivers: IDriver[] = []; - constructor(readonly service: IPositronConnectionsService) { - this.registerDefaultDrivers(); - } + constructor(readonly service: IPositronConnectionsService) { } registerDriver(driver: IDriver): void { // Check that a driver with the same id does not already exist. @@ -35,114 +31,4 @@ export class PositronConnectionsDriverManager { getDrivers(): IDriver[] { return this.drivers; } - - private registerDefaultDrivers(): void { - this.registerDriver(new RPostgreSQLDriver(this.service)); - } -} - - -class RPostgreSQLDriver implements IDriver { - constructor(readonly service: IPositronConnectionsService) { } - - driverId: string = 'postgres'; - - metadata: IDriverMetadata = { - languageId: 'r', - name: 'PostgresSQL', - inputs: [ - { - 'id': 'dbname', - 'label': 'Database Name', - 'type': 'string', - 'value': 'localhost' - }, - { - 'id': 'host', - 'label': 'Host', - 'type': 'string', - 'value': 'localhost' - }, - { - 'id': 'port', - 'label': 'Port', - 'type': 'number', - 'value': '5432' - }, - { - 'id': 'user', - 'label': 'User', - 'type': 'string', - 'value': 'postgres' - }, - { - 'id': 'password', - 'label': 'Password', - 'type': 'string', - 'value': 'password' - }, - { - 'id': 'bigint', - 'label': 'Integer representation', - 'type': 'option', - 'options': [ - { 'identifier': 'integer64', 'title': 'integer64' }, - { 'identifier': 'integer', 'title': 'integer' }, - { 'identifier': 'numeric', 'title': 'numeric' }, - { 'identifier': 'character', 'title': 'character' } - ], - 'value': 'integer64' - } - ] - } - - async generateCode(inputs: Array) { - const dbname = inputs.find(input => input.id === 'dbname')?.value; - const host = inputs.find(input => input.id === 'host')?.value; - const port = inputs.find(input => input.id === 'port')?.value; - const user = inputs.find(input => input.id === 'user')?.value; - const password = inputs.find(input => input.id === 'password')?.value; - const bigint = inputs.find(input => input.id === 'bigint')?.value; - - return `library(DBI) - con <- dbConnect( - RPostgres::Postgres(), - dbname = '${dbname ?? ''}', - host = '${host ?? ''}', - port = ${port ?? ''}, - user = '${user ?? ''}', - password = '${password ?? ''}', - bigint = '${bigint ?? ''}' -) -`; - } - - async connect(code: string) { - // Check if the foreground session is an R session. - const session = this.getSession(); - - if (!session) { - throw new Error('No R session found. Create an R session and retry.'); - } - - // We don't get to know if something failed. That's fine for now as the error would be displayed - // in the console. - session.execute(code, 'connect', RuntimeCodeExecutionMode.Interactive, RuntimeErrorBehavior.Stop); - } - - getSession(): ILanguageRuntimeSession | undefined { - const foregroundSession = this.service.runtimeSessionService.foregroundSession; - if (foregroundSession && foregroundSession.runtimeMetadata.languageId === 'r') { - return foregroundSession; - } - - // If no foreground session, we'll check if there's a running R session. - const session = this.service.runtimeSessionService.activeSessions.find(session => session.runtimeMetadata.languageId === 'r'); - if (session) { - return session; - } - - // No running R session. For now we don't do anything to start a new session. - return undefined; - } } diff --git a/src/vs/workbench/services/positronConnections/browser/positronConnectionsInstance.ts b/src/vs/workbench/services/positronConnections/browser/positronConnectionsInstance.ts index c8463f7a85c..a95d2e53e07 100644 --- a/src/vs/workbench/services/positronConnections/browser/positronConnectionsInstance.ts +++ b/src/vs/workbench/services/positronConnections/browser/positronConnectionsInstance.ts @@ -6,13 +6,13 @@ import { Disposable } from '../../../../base/common/lifecycle.js'; import { Emitter, Event } from '../../../../base/common/event.js'; import { ConnectionsClientInstance } from '../../languageRuntime/common/languageRuntimeConnectionsClient.js'; -import { ConnectionMetadata, IPositronConnectionInstance, IPositronConnectionItem } from './interfaces/positronConnectionsInstance.js'; +import { ConnectionMetadata, IPositronConnectionInstance, IPositronConnectionItem, IPositronConnectionEntry } from '../common/interfaces/positronConnectionsInstance.js'; import { ObjectSchema } from '../../languageRuntime/common/positronConnectionsComm.js'; import { IRuntimeSessionService } from '../../runtimeSession/common/runtimeSessionService.js'; import { RuntimeCodeExecutionMode, RuntimeErrorBehavior } from '../../languageRuntime/common/languageRuntimeService.js'; -import { flatten_children, IPositronConnectionEntry } from './positronConnectionsUtils.js'; +import { flatten_children } from './positronConnectionsUtils.js'; import { Severity } from '../../../../platform/notification/common/notification.js'; -import { IPositronConnectionsService } from './interfaces/positronConnectionsService.js'; +import { IPositronConnectionsService } from '../common/interfaces/positronConnectionsService.js'; import { DeferredPromise } from '../../../../base/common/async.js'; import { localize } from '../../../../nls.js'; diff --git a/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts b/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts index f7cc5169515..fa096e4380a 100644 --- a/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts +++ b/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts @@ -6,8 +6,8 @@ import { Disposable } from '../../../../base/common/lifecycle.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; import { ConnectionsClientInstance } from '../../languageRuntime/common/languageRuntimeConnectionsClient.js'; -import { ConnectionMetadata, IConnectionMetadata, IPositronConnectionInstance } from './interfaces/positronConnectionsInstance.js'; -import { IPositronConnectionsService, POSITRON_CONNECTIONS_VIEW_ID } from './interfaces/positronConnectionsService.js'; +import { ConnectionMetadata, IConnectionMetadata, IPositronConnectionInstance } from '../common/interfaces/positronConnectionsInstance.js'; +import { IPositronConnectionsService, POSITRON_CONNECTIONS_VIEW_ID } from '../common/interfaces/positronConnectionsService.js'; import { DisconnectedPositronConnectionsInstance, PositronConnectionsInstance } from './positronConnectionsInstance.js'; import { ILanguageRuntimeSession, IRuntimeSessionService, RuntimeClientType } from '../../runtimeSession/common/runtimeSessionService.js'; import { Event, Emitter } from '../../../../base/common/event.js'; diff --git a/src/vs/workbench/services/positronConnections/browser/positronConnectionsUtils.ts b/src/vs/workbench/services/positronConnections/browser/positronConnectionsUtils.ts index 5ccd0e78590..d8352e49cd8 100644 --- a/src/vs/workbench/services/positronConnections/browser/positronConnectionsUtils.ts +++ b/src/vs/workbench/services/positronConnections/browser/positronConnectionsUtils.ts @@ -4,24 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from '../../../../base/common/lifecycle.js'; -import { IPositronConnectionItem } from './interfaces/positronConnectionsInstance.js'; - -export interface IPositronConnectionEntry extends IPositronConnectionItem { - /*** - * The list of connections entries is flat. Level allows us to find - * how nested an entry is. - */ - level: number; - - /*** - * If the entry is expanded or not. Undefined if the entry is not expandable. - */ - expanded?: boolean; - - // If an error happens during some evaluation for that element - // we try to display some information . - error?: string; -} +import { IPositronConnectionItem, IPositronConnectionEntry } from '../common/interfaces/positronConnectionsInstance.js'; + + class PositronConnectionEntry extends Disposable implements IPositronConnectionEntry { diff --git a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsDriver.ts b/src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsDriver.ts similarity index 100% rename from src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsDriver.ts rename to src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsDriver.ts diff --git a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts b/src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsInstance.ts similarity index 84% rename from src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts rename to src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsInstance.ts index e04a478c34f..9a2ad15eac3 100644 --- a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts +++ b/src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsInstance.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from '../../../../../base/common/event.js'; -import { IPositronConnectionEntry } from '../positronConnectionsUtils.js'; export interface IConnectionMetadata { name: string; @@ -79,3 +78,20 @@ export interface IPositronConnectionItem { hasChildren?(): Promise; getChildren?(): Promise; } + +export interface IPositronConnectionEntry extends IPositronConnectionItem { + /*** + * The list of connections entries is flat. Level allows us to find + * how nested an entry is. + */ + level: number; + + /*** + * If the entry is expanded or not. Undefined if the entry is not expandable. + */ + expanded?: boolean; + + // If an error happens during some evaluation for that element + // we try to display some information . + error?: string; +} diff --git a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsService.ts b/src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsService.ts similarity index 95% rename from src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsService.ts rename to src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsService.ts index 5ecacbfb1f6..7885ac8031d 100644 --- a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsService.ts +++ b/src/vs/workbench/services/positronConnections/common/interfaces/positronConnectionsService.ts @@ -9,7 +9,7 @@ import { Emitter, Event } from '../../../../../base/common/event.js'; import Severity from '../../../../../base/common/severity.js'; import { INotificationHandle } from '../../../../../platform/notification/common/notification.js'; import { IRuntimeSessionService } from '../../../runtimeSession/common/runtimeSessionService.js'; -import { PositronConnectionsDriverManager } from '../positronConnectionsDrivers.js'; +import { PositronConnectionsDriverManager } from '../../browser/positronConnectionsDrivers.js'; export const IPositronConnectionsService = createDecorator('positronConnectionsService'); export const POSITRON_CONNECTIONS_VIEW_ID = 'workbench.panel.positronConnections'; From 2d721eb92219b8f1b841b558c122959273c235cf Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 18 Dec 2024 13:44:59 -0300 Subject: [PATCH 4/7] Unregister the driver when the extension is unloaded. --- extensions/positron-r/src/connections.ts | 7 +++++-- extensions/positron-r/src/extension.ts | 2 +- .../api/common/positron/extHost.positron.api.impl.ts | 6 ++++++ src/vs/workbench/api/common/positron/extHostConnections.ts | 7 ++++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/extensions/positron-r/src/connections.ts b/extensions/positron-r/src/connections.ts index bc78542c959..8bdc06b95b1 100644 --- a/extensions/positron-r/src/connections.ts +++ b/extensions/positron-r/src/connections.ts @@ -4,9 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as positron from 'positron'; +import * as vscode from 'vscode'; -export function registerConnectionDrivers() { - positron.connections.registerConnectionDriver(new RPostgreSQLDriver()); +export function registerConnectionDrivers(context: vscode.ExtensionContext) { + context.subscriptions.push( + positron.connections.registerConnectionDriver(new RPostgreSQLDriver()) + ); } class RPostgreSQLDriver implements positron.ConnectionsDriver { diff --git a/extensions/positron-r/src/extension.ts b/extensions/positron-r/src/extension.ts index 79ddf5755d5..ea1c14175be 100644 --- a/extensions/positron-r/src/extension.ts +++ b/extensions/positron-r/src/extension.ts @@ -50,5 +50,5 @@ export function activate(context: vscode.ExtensionContext) { }); // Register connection drivers. - registerConnectionDrivers(); + registerConnectionDrivers(context); } diff --git a/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts b/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts index f21dc1256d2..90255559458 100644 --- a/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts +++ b/src/vs/workbench/api/common/positron/extHost.positron.api.impl.ts @@ -195,6 +195,12 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce }; const connections: typeof positron.connections = { + /** + * Register a connection driver that's used to generate code for connecting to a data source + * using the 'New Connection' dialog. + * @param driver The connection driver to register. + * @returns A disposable that can be used to unregister the driver. + */ registerConnectionDriver(driver: positron.ConnectionsDriver): vscode.Disposable { return extHostConnections.registerConnectionDriver(driver); } diff --git a/src/vs/workbench/api/common/positron/extHostConnections.ts b/src/vs/workbench/api/common/positron/extHostConnections.ts index a2d2a64501d..d38a8717b85 100644 --- a/src/vs/workbench/api/common/positron/extHostConnections.ts +++ b/src/vs/workbench/api/common/positron/extHostConnections.ts @@ -39,7 +39,12 @@ export class ExtHostConnections implements extHostProtocol.ExtHostConnectionsSha installDependencies: driver.installDependencies ? true : false } ); - return new Disposable(() => { }); + + // When the driver is disposed, remove it from the list and notify the main thread + return new Disposable(() => { + this._drivers = this._drivers.filter(d => d.driverId !== driver.driverId); + this._proxy.$removeConnectionDriver(driver.driverId); + }); } public async $driverGenerateCode(driverId: string, inputs: Input[]) { From f63d056bad1d3af7308d0f3f8c81acad55aac766 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 18 Dec 2024 15:16:17 -0300 Subject: [PATCH 5/7] Move to the connections extension instead --- .../connections.ts => positron-connections/src/drivers.ts} | 0 extensions/positron-connections/src/extension.ts | 3 +++ extensions/positron-r/src/extension.ts | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) rename extensions/{positron-r/src/connections.ts => positron-connections/src/drivers.ts} (100%) diff --git a/extensions/positron-r/src/connections.ts b/extensions/positron-connections/src/drivers.ts similarity index 100% rename from extensions/positron-r/src/connections.ts rename to extensions/positron-connections/src/drivers.ts diff --git a/extensions/positron-connections/src/extension.ts b/extensions/positron-connections/src/extension.ts index d3aab1d7aa1..2454d28ee2e 100644 --- a/extensions/positron-connections/src/extension.ts +++ b/extensions/positron-connections/src/extension.ts @@ -7,9 +7,12 @@ import * as vscode from 'vscode'; import * as positron from 'positron'; import { ConnectionItem, ConnectionItemsProvider, isActiveConnectionItem, DatabaseConnectionItem, DisconnectedConnectionItem } from './connection'; import { PositronConnectionsComm } from './comms/ConnectionsComms'; +import { registerConnectionDrivers } from './drivers'; export function activate(context: vscode.ExtensionContext) { + // We always register the drivers. + registerConnectionDrivers(context); const config = vscode.workspace.getConfiguration('positron'); const enabled = !config.get('connections', false); diff --git a/extensions/positron-r/src/extension.ts b/extensions/positron-r/src/extension.ts index ea1c14175be..26963c07caf 100644 --- a/extensions/positron-r/src/extension.ts +++ b/extensions/positron-r/src/extension.ts @@ -13,7 +13,6 @@ import { setContexts } from './contexts'; import { setupTestExplorer, refreshTestExplorer } from './testing/testing'; import { RRuntimeManager } from './runtime-manager'; import { registerUriHandler } from './uri-handler'; -import { registerConnectionDrivers } from './connections'; export const LOGGER = vscode.window.createOutputChannel('Positron R Extension', { log: true }); @@ -48,7 +47,4 @@ export function activate(context: vscode.ExtensionContext) { refreshTestExplorer(context); } }); - - // Register connection drivers. - registerConnectionDrivers(context); } From 4a251048ab3afa84a4b3a7b4998062f467684ec3 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 18 Dec 2024 16:36:06 -0300 Subject: [PATCH 6/7] Add disposing --- .../workbench/api/browser/positron/mainThreadConnections.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/positron/mainThreadConnections.ts b/src/vs/workbench/api/browser/positron/mainThreadConnections.ts index a217e359a99..a2cc2699fd7 100644 --- a/src/vs/workbench/api/browser/positron/mainThreadConnections.ts +++ b/src/vs/workbench/api/browser/positron/mainThreadConnections.ts @@ -7,10 +7,12 @@ import { ExtHostConnectionsShape, ExtHostPositronContext, MainPositronContext, M import { extHostNamedCustomer, IExtHostContext } from '../../../services/extensions/common/extHostCustomers.js'; import { IDriver, IDriverMetadata, Input } from '../../../services/positronConnections/common/interfaces/positronConnectionsDriver.js'; import { IPositronConnectionsService } from '../../../services/positronConnections/common/interfaces/positronConnectionsService.js'; +import { DisposableStore } from '../../../../base/common/lifecycle.js'; @extHostNamedCustomer(MainPositronContext.MainThreadConnections) export class MainThreadConnections implements MainThreadConnectionsShape { private readonly _proxy: ExtHostConnectionsShape; + private readonly _disposables = new DisposableStore(); constructor( extHostContext: IExtHostContext, @IPositronConnectionsService private readonly _connectionsService: IPositronConnectionsService @@ -29,7 +31,7 @@ export class MainThreadConnections implements MainThreadConnectionsShape { } dispose(): void { - + this._disposables.dispose(); } } From 58b9db006a5e4725d64ff4e043eaa70c4427481f Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 18 Dec 2024 16:41:58 -0300 Subject: [PATCH 7/7] Add docs --- src/positron-dts/positron.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/positron-dts/positron.d.ts b/src/positron-dts/positron.d.ts index 1c56a155ffa..c9c0065a5c5 100644 --- a/src/positron-dts/positron.d.ts +++ b/src/positron-dts/positron.d.ts @@ -1439,6 +1439,13 @@ declare module 'positron' { * Refers to methods related to the connections pane */ namespace connections { + /** + * Registers a new connection driver with Positron allowing extensions to contribute + * to the 'New Connection' dialog. + * + * @param driver The connection driver to register + * @returns A disposable that unregisters the driver when disposed + */ export function registerConnectionDriver(driver: ConnectionsDriver): vscode.Disposable; } }