-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: enhance existing Execute REST API command to remember last used…
… APIs
- Loading branch information
Showing
1 changed file
with
117 additions
and
26 deletions.
There are no files selected for viewing
143 changes: 117 additions & 26 deletions
143
packages/vscode-extension/src/commands/execRestApiCommand.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,144 @@ | ||
import * as vscode from 'vscode'; | ||
|
||
import { HttpMethod, HttpRequestInfo } from '@vlocode/salesforce'; | ||
import { Timer } from '@vlocode/util'; | ||
|
||
import { VlocodeCommand } from '../constants'; | ||
import { vscodeCommand } from '../lib/commandRouter'; | ||
import { HttpMethod } from '@vlocode/salesforce'; | ||
import { Timer } from '@vlocode/util'; | ||
import * as vscode from 'vscode'; | ||
import { ApiRequestDocumentParser } from '../lib/salesforce/apiRequestDocumentParser'; | ||
import MetadataCommand from './metadata/metadataCommand'; | ||
|
||
@vscodeCommand(VlocodeCommand.execRestApi) | ||
export default class ExecuteRestApiCommand extends MetadataCommand { | ||
public async execute() { | ||
let url = await vscode.window.showInputBox({ placeHolder: 'Enter the Salesforce API endpoint', ignoreFocusOut: true }); | ||
|
||
private httpMethodOptions: Array<{ label: string, method: HttpMethod, allowsBody?: boolean }> = [ | ||
{ label: 'GET', method: 'GET' }, | ||
{ label: 'POST', method: 'POST', allowsBody: true }, | ||
{ label: 'PATCH', method: 'PATCH', allowsBody: true }, | ||
{ label: 'PUT', method: 'PUT', allowsBody: true }, | ||
{ label: 'DELETE', method: 'DELETE' } | ||
]; | ||
|
||
public async execute(args?: HttpRequestInfo | vscode.Uri) { | ||
if (args instanceof vscode.Uri) { | ||
const document = await vscode.workspace.openTextDocument(args); | ||
await this.executeRequestFromDocument(document); | ||
} else if (typeof args === 'object') { | ||
await this.executeRequest(args); | ||
} else { | ||
const request = await this.showRecentRequests() ?? await this.showRequestInput(); | ||
request && await this.executeRequest(request); | ||
} | ||
} | ||
|
||
private async executeRequestFromDocument(document: vscode.TextDocument) { | ||
const request = await ApiRequestDocumentParser.parse(document); | ||
await this.executeRequest(request); | ||
} | ||
|
||
private async showRequestInput() : Promise<HttpRequestInfo | undefined> { | ||
const url = await vscode.window.showInputBox({ | ||
placeHolder: 'Enter the relative Salesforce API endpoint URI', | ||
ignoreFocusOut: true | ||
}); | ||
|
||
if (!url) { | ||
return; | ||
} | ||
|
||
const method = await vscode.window.showQuickPick( | ||
[ 'GET', 'POST' ], | ||
{ placeHolder: 'Select HTTP Method', ignoreFocusOut: true }) as HttpMethod; | ||
if (!method) { | ||
const selectedMethod = await vscode.window.showQuickPick( | ||
this.httpMethodOptions, | ||
{ | ||
placeHolder: 'Select HTTP Method', | ||
ignoreFocusOut: true | ||
} | ||
); | ||
|
||
if (!selectedMethod) { | ||
return; | ||
} | ||
|
||
// transform into valid REST API | ||
if (!url.startsWith('/services')) { | ||
// assume APEX rest url when not prefixed with services | ||
url = `/services/apexrest/${url}`.replace(/[/]+/g, '/'); | ||
const body = selectedMethod.allowsBody | ||
? await vscode.window.showInputBox({ | ||
placeHolder: 'Enter POST body', | ||
ignoreFocusOut: true | ||
}) : undefined; | ||
|
||
return { | ||
url, | ||
method: selectedMethod.method, | ||
body | ||
}; | ||
} | ||
|
||
private async showRecentRequests() : Promise<HttpRequestInfo | undefined> { | ||
const recent = this.context.recent.get<HttpRequestInfo>('apiRequests'); | ||
if (!recent.length) { | ||
return; | ||
} | ||
|
||
let body; | ||
if (method == 'POST') { | ||
body = await vscode.window.showInputBox({ placeHolder: 'Enter POST body', ignoreFocusOut: true }); | ||
if (!body) { | ||
return; | ||
const options = [ | ||
...recent.map(r => ({ label: `${r.method} ${r.url}`, request: r })), | ||
...[{ | ||
label: '', | ||
kind: vscode.QuickPickItemKind.Separator | ||
},{ | ||
label: '$(add) New request', | ||
request: undefined | ||
},{ | ||
label: '$(trashcan) Clear recent requests', | ||
action: 'clear' | ||
}] | ||
]; | ||
|
||
const selected = await vscode.window.showQuickPick(options, { | ||
placeHolder: 'Select recent request', | ||
ignoreFocusOut: true | ||
}); | ||
|
||
if (selected) { | ||
if ('request' in selected) { | ||
return selected.request; | ||
} | ||
|
||
if ('action' in selected && selected.action === 'clear') { | ||
this.context.recent.clear('apiRequests'); | ||
} | ||
} | ||
} | ||
|
||
private async executeRequest(request: HttpRequestInfo) { | ||
// normalize request | ||
request.method = request.method.toUpperCase() as HttpMethod; | ||
if (!request.url.startsWith('/services')) { | ||
// assume APEX rest url when not prefixed with services | ||
request.url = `/services/apexrest/${request.url}`.replace(/[/]+/g, '/'); | ||
} | ||
|
||
// add to recent requests | ||
this.context.recent.add('apiRequests', request, { | ||
equals: (a, b) => a.method === b.method && a.url === b.url | ||
}); | ||
|
||
this.logger.info(`Invoking ${url} as ${method}`); | ||
const timer = new Timer(); | ||
const connection = await this.salesforce.getJsForceConnection(); | ||
const request = { method, url, body }; | ||
const response = await this.vlocode.withActivity({ | ||
progressTitle: `${method} ${url}...`, | ||
progressTitle: `${request.method} ${request.url}...`, | ||
location: vscode.ProgressLocation.Notification, | ||
cancellable: false | ||
}, () => connection.request(request)); | ||
this.logger.info(`${method} ${url} [${timer.stop()}]`); | ||
}, async () => { | ||
const connection = await this.salesforce.getJsForceConnection(); | ||
return await connection.request(request); | ||
}); | ||
this.logger.info(`${request.method} ${request.url} [${timer.stop()}]`); | ||
|
||
const responseDocument = await vscode.workspace.openTextDocument({ | ||
language: 'json', | ||
content: JSON.stringify(response, null, 4) | ||
}); | ||
|
||
const responseDocument = await vscode.workspace.openTextDocument({ language: 'json', content: JSON.stringify(response, null, 4) }); | ||
if (responseDocument) { | ||
void vscode.window.showTextDocument(responseDocument); | ||
} | ||
} | ||
} | ||
} | ||
|