Skip to content

Commit

Permalink
vscode-lib: expose vscode API via global
Browse files Browse the repository at this point in the history
Currently vscode doesn't support dynamic imports, so it isn't possible
for a javascript provider to opt-in to more advanced user experience via
the vscode APIs.

Until we can more easily opt-in to vscode support, we expose the vscode
API via node's global object. We want to see what sort of APIs get used
from vscode in providers, and will then likely evolve a first class
editor abstraction.
  • Loading branch information
keegancsmith committed Jun 27, 2024
1 parent 0b8b5d9 commit 56e8b60
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 4 deletions.
2 changes: 1 addition & 1 deletion client/vscode-lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openctx/vscode-lib",
"version": "0.0.11",
"version": "0.0.12",
"description": "OpenCtx library for VS Code extensions",
"license": "Apache-2.0",
"repository": {
Expand Down
3 changes: 3 additions & 0 deletions client/vscode-lib/src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Cache, bestEffort } from './util/cache.js'
import { ErrorReporterController, UserAction } from './util/errorReporter.js'
import { importProvider } from './util/importHelpers.js'
import { observeWorkspaceConfigurationChanges, toEventEmitter } from './util/observable.js'
import { initializeOpenCtxGlobal } from './global.js'

type VSCodeClient = Client<vscode.Range>

Expand Down Expand Up @@ -61,6 +62,8 @@ export function createController({
apiForTesting: ExtensionApiForTesting
disposable: vscode.Disposable
} {
initializeOpenCtxGlobal()

const disposables: vscode.Disposable[] = []

const globalConfigurationChanges = observeWorkspaceConfigurationChanges('openctx')
Expand Down
23 changes: 23 additions & 0 deletions client/vscode-lib/src/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as vscode from 'vscode'

// dynamic imports don't work in node + vscode due to
// https://github.com/microsoft/vscode-loader/issues/36
//
// So vscode-lib sets a global so providers can optionally access vscode APIs.

interface Global {
openctx?: {
vscode?: typeof vscode
}
}

export function initializeOpenCtxGlobal() {
initializeGlobal(global as Global)
}

function initializeGlobal(global: Global) {
if (!global.openctx) {
global.openctx = { vscode }
}
global.openctx.vscode = vscode
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

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

52 changes: 52 additions & 0 deletions provider/linear-issues/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ async function getAccessToken(settings: Settings): Promise<string> {
return userCredentials.access_token
}

const vscodeAccessToken = await getAccessTokenLinearConnect()
if (vscodeAccessToken) {
return vscodeAccessToken
}

throw new Error(
'must provide a Linear user credentials path in the `userCredentialsPath` settings field or an accessToken in the linearClientOptions'
)
Expand Down Expand Up @@ -157,6 +162,53 @@ async function linearApiRequest(
return json
}

const LINEAR_AUTHENTICATION_EXTENSION_ID = 'linear.linear-connect'
const LINEAR_AUTHENTICATION_PROVIDER_ID = 'linear'
const LINEAR_AUTHENTICATION_SCOPES = ['read']

function vscodeAPI() {
// dynamic imports don't work in node + vscode due
// https://github.com/microsoft/vscode-loader/issues/36 vscode-lib however
// will sneakily set the vscode import to a global for us.
if (!('openctx' in global)) {
return undefined
}
const openctx = (global as any).openctx
if (!openctx.vscode) {
return undefined
}
return openctx.vscode as typeof import('vscode')
}

async function getAccessTokenLinearConnect(): Promise<string | undefined> {
const vscode = vscodeAPI()
if (!vscode) {
return undefined
}

const ext = vscode.extensions.getExtension(LINEAR_AUTHENTICATION_EXTENSION_ID)
if (!ext) {
vscode.window.showWarningMessage(
'Cody requires the Linear Connect extension to be installed and activated.'
)
await vscode.commands.executeCommand('workbench.extensions.action.showExtensionsWithIds', [
[LINEAR_AUTHENTICATION_EXTENSION_ID],
])
}

const session = await vscode.authentication.getSession(
LINEAR_AUTHENTICATION_PROVIDER_ID,
LINEAR_AUTHENTICATION_SCOPES,
{ createIfNone: true }
)

if (!session) {
throw new Error(`We weren't able to log you into Linear when trying to open the issue.`)
}

return session.accessToken
}

function parseIssueIDFromURL(urlStr: string): string | undefined {
const url = new URL(urlStr)
if (!url.hostname.endsWith('linear.app')) {
Expand Down
7 changes: 4 additions & 3 deletions provider/linear-issues/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openctx/provider-linear-issues",
"version": "0.0.3",
"version": "0.0.4",
"description": "Linear Issues context for code AI and editors (OpenCtx provider)",
"license": "Apache-2.0",
"repository": {
Expand All @@ -19,7 +19,7 @@
"scripts": {
"build": "tsc --build",
"bundle:watch": "pnpm run bundle --watch",
"bundle": "esbuild --main-fields=module,main --log-level=error --platform=node --bundle --format=esm --outfile=dist/bundle.js index.ts",
"bundle": "esbuild --main-fields=module,main --external:vscode --log-level=error --platform=node --bundle --format=esm --outfile=dist/bundle.js index.ts",
"prepublishOnly": "tsc --build --clean && pnpm run --silent bundle",
"test": "vitest",
"auth": "node --no-warnings=ExperimentalWarning --es-module-specifier-resolution=node --loader ts-node/esm/transpile-only auth.ts"
Expand All @@ -32,6 +32,7 @@
"server-destroy": "^1.0.1"
},
"devDependencies": {
"@types/server-destroy": "^1.0.3"
"@types/server-destroy": "^1.0.3",
"@types/vscode": "^1.85.0"
}
}

0 comments on commit 56e8b60

Please sign in to comment.