This repository has been archived by the owner on Jul 31, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(CodeLens): and configuration fixes (#58)
* bump: version for 0.0.10 * feat: codelens without query * feat: inline playground and codelens * feat: codelens, extract graphql response from apollo response * feat: codelens, ignore template variables for now * fix: regex * bump version for release * fix: configuration, update deps * fix: deps * fix: add codelens only for executable operations * bump version * fix: support scalars, code clean up * fix: codelens, add support for object type * fix: codegen, handle lists as input * fix: codelens, constructor * bump version for internal release * dep: add subscriptions-transport-ws * fix: add catch brackets * fix: added parameter to constructor * chore: add fish shell support * chore: bump version * fix: race condition between input and content provider * bump version * beta: mark as preview * bump version
- Loading branch information
Divyendu Singh
authored
Aug 18, 2018
1 parent
d36a11f
commit 93ca640
Showing
9 changed files
with
1,373 additions
and
621 deletions.
There are no files selected for viewing
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
Large diffs are not rendered by default.
Oops, something went wrong.
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
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 |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { | ||
OutputChannel, | ||
CodeLensProvider, | ||
TextDocument, | ||
CancellationToken, | ||
CodeLens, | ||
Range, | ||
Position, | ||
} from "vscode" | ||
|
||
import { SourceHelper, ExtractedTemplateLiteral } from "./source-helper" | ||
import { OperationDefinitionNode } from "graphql" | ||
import * as capitalize from "capitalize" | ||
|
||
export class GraphQLCodeLensProvider implements CodeLensProvider { | ||
outputChannel: OutputChannel | ||
sourceHelper: SourceHelper | ||
|
||
constructor(outputChannel: OutputChannel) { | ||
this.outputChannel = outputChannel | ||
this.sourceHelper = new SourceHelper(this.outputChannel) | ||
} | ||
|
||
public provideCodeLenses( | ||
document: TextDocument, | ||
token: CancellationToken, | ||
): CodeLens[] | Thenable<CodeLens[]> { | ||
const literals: ExtractedTemplateLiteral[] = this.sourceHelper.extractAllTemplateLiterals( | ||
document, | ||
["gql", "graphql"], | ||
) | ||
return literals.map(literal => { | ||
return new CodeLens( | ||
new Range( | ||
new Position(literal.position.line, 0), | ||
new Position(literal.position.line, 0), | ||
), | ||
{ | ||
title: `Execute ${capitalize( | ||
(literal.ast.definitions[0] as OperationDefinitionNode).operation, | ||
)}`, | ||
command: "extension.contentProvider", | ||
arguments: [literal], | ||
}, | ||
) | ||
}) | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,182 @@ | ||
import { | ||
workspace, | ||
OutputChannel, | ||
TextDocumentContentProvider, | ||
EventEmitter, | ||
Uri, | ||
Event, | ||
ProviderResult, | ||
window | ||
} from "vscode"; | ||
|
||
import { ExtractedTemplateLiteral } from "./source-helper"; | ||
import { | ||
GraphQLConfig, | ||
getGraphQLConfig, | ||
GraphQLProjectConfig | ||
} from "graphql-config"; | ||
import { visit, VariableDefinitionNode } from "graphql"; | ||
import { NetworkHelper } from "./network-helper"; | ||
import { SourceHelper, GraphQLScalarTSType } from "./source-helper"; | ||
|
||
export class GraphQLContentProvider implements TextDocumentContentProvider { | ||
private uri: Uri; | ||
private outputChannel: OutputChannel; | ||
private networkHelper: NetworkHelper; | ||
private sourceHelper: SourceHelper; | ||
|
||
// Event emitter which invokes document updates | ||
private _onDidChange = new EventEmitter<Uri>(); | ||
|
||
private html: string = ""; // HTML document buffer | ||
|
||
timeout = ms => new Promise(res => setTimeout(res, ms)); | ||
|
||
async getVariablesFromUser( | ||
variableDefinitionNodes: VariableDefinitionNode[] | ||
): Promise<{ [key: string]: GraphQLScalarTSType }> { | ||
await this.timeout(500); | ||
let variables = {}; | ||
for (let node of variableDefinitionNodes) { | ||
variables = { | ||
...variables, | ||
[`${node.variable.name.value}`]: this.sourceHelper.typeCast( | ||
await window.showInputBox({ | ||
ignoreFocusOut: true, | ||
placeHolder: `Please enter the value for ${ | ||
node.variable.name.value | ||
}` | ||
}), | ||
this.sourceHelper.getTypeForVariableDefinitionNode(node) | ||
) | ||
}; | ||
} | ||
return variables; | ||
} | ||
|
||
/* | ||
Use the configration of first project if heuristics failed | ||
to find one. | ||
*/ | ||
patchProjectConfig(config: GraphQLConfig) { | ||
if (!config.config.projects) { | ||
return config; | ||
} | ||
if (config.config.projects) { | ||
const projectKeys = Object.keys(config.config.projects); | ||
return config.getProjectConfig(projectKeys[0]); | ||
} | ||
return null; | ||
} | ||
|
||
constructor( | ||
uri: Uri, | ||
outputChannel: OutputChannel, | ||
literal: ExtractedTemplateLiteral | ||
) { | ||
this.uri = uri; | ||
this.outputChannel = outputChannel; | ||
this.networkHelper = new NetworkHelper(this.outputChannel); | ||
this.sourceHelper = new SourceHelper(this.outputChannel); | ||
|
||
try { | ||
const rootDir = workspace.getWorkspaceFolder(Uri.file(literal.uri)); | ||
if (!rootDir) { | ||
this.outputChannel.appendLine( | ||
`Error: this file is outside the workspace.` | ||
); | ||
this.html = "Error: this file is outside the workspace."; | ||
this.update(this.uri); | ||
return; | ||
} else { | ||
const config = getGraphQLConfig(rootDir!.uri.fsPath); | ||
let projectConfig = config.getConfigForFile(literal.uri); | ||
if (!projectConfig) { | ||
projectConfig = this.patchProjectConfig( | ||
config | ||
) as GraphQLProjectConfig; | ||
} | ||
|
||
if (!projectConfig!.endpointsExtension) { | ||
this.outputChannel.appendLine( | ||
`Error: endpoint data missing from graphql config` | ||
); | ||
this.html = "Error: endpoint data missing from graphql config"; | ||
this.update(this.uri); | ||
return; | ||
} | ||
|
||
const endpointNames = Object.keys( | ||
projectConfig!.endpointsExtension!.getRawEndpointsMap() | ||
); | ||
|
||
if (endpointNames.length === 0) { | ||
this.outputChannel.appendLine( | ||
`Error: endpoint data missing from graphql config endpoints extension` | ||
); | ||
this.html = | ||
"Error: endpoint data missing from graphql config endpoints extension"; | ||
this.update(this.uri); | ||
return; | ||
} | ||
|
||
// TODO: Can ask user for the endpoint if muliple exist | ||
// Endpoints extensions docs say that at least "default" will be there | ||
const endpointName = endpointNames[0]; | ||
const endpoint = projectConfig!.endpointsExtension!.getEndpoint( | ||
endpointName | ||
); | ||
|
||
let variableDefinitionNodes: VariableDefinitionNode[] = []; | ||
visit(literal.ast, { | ||
VariableDefinition(node: VariableDefinitionNode) { | ||
variableDefinitionNodes.push(node); | ||
} | ||
}); | ||
|
||
const updateCallback = (data: string, operation: string) => { | ||
if (operation === "subscription") { | ||
this.html = `<pre>${data}</pre>` + this.html; | ||
} else { | ||
this.html += `<pre>${data}</pre>`; | ||
} | ||
this.update(this.uri); | ||
}; | ||
|
||
if (variableDefinitionNodes.length > 0) { | ||
this.getVariablesFromUser(variableDefinitionNodes).then( | ||
(variables: any) => { | ||
this.networkHelper.executeOperation({ | ||
endpoint: endpoint, | ||
literal: literal, | ||
variables: variables, | ||
updateCallback | ||
}); | ||
} | ||
); | ||
} else { | ||
this.networkHelper.executeOperation({ | ||
endpoint: endpoint, | ||
literal: literal, | ||
variables: {}, | ||
updateCallback | ||
}); | ||
} | ||
} | ||
} catch (e) { | ||
this.html = e.toString(); | ||
} | ||
} | ||
|
||
get onDidChange(): Event<Uri> { | ||
return this._onDidChange.event; | ||
} | ||
|
||
public update(uri: Uri) { | ||
this._onDidChange.fire(uri); | ||
} | ||
|
||
provideTextDocumentContent(_: Uri): ProviderResult<string> { | ||
return this.html; | ||
} | ||
} |
Oops, something went wrong.