Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
Making the great [GraphiQL tool](https://github.com/graphql/graphiql/) available anywhere as a Chrome extension.

Based on the [GraphiQL example code](https://github.com/graphql/graphiql/tree/master/example).

With option to add headers. Header format is JSON or "HEADER_NAME:HEADER_VALUE;"
23 changes: 22 additions & 1 deletion css/chromeiql.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ body {
display: flex;
}

#url-bar {
#input-bar {
width: 600px;
position: absolute;
text-align: center;
Expand Down Expand Up @@ -47,3 +47,24 @@ body {
#url-save-button {
padding: 6px 12px;
}

#headers-box, #headers-save-button {
height: 30px;
box-sizing: border-box;
margin: 3px auto;
}

#headers-box {
width: 500px;
margin-right: 2px;
border-radius: 4px;
margin-right: 2px;
padding: 0 4px;
border: 1px none;
border-style: inset;
color: #555;
}

#url-save-button {
padding: 6px 12px;
}
81 changes: 74 additions & 7 deletions js/chromeiql.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import $ from 'jquery';
// Buffer for endpoint entry value
let chromeiqlEndpoint;

// Buffer for headers value
let chromeiqlHeaders;

// Parse the search string to get url parameters.
const search = window.location.search;
let parameters = {};
Expand Down Expand Up @@ -49,12 +52,38 @@ function updateURL() {
history.replaceState(null, null, newSearch);
}

function createHeaders(headers) {
const retHeaders = new Headers({'Content-Type': 'application/json'});
if (headers) {
let hconv = string2Header(headers);
for (let header of hconv) {
if (header.length !== 2) continue;
retHeaders.append(header[0], header[1]);
}
}
return retHeaders;
}

const string2Header = (str) => {
if (str && typeof str === 'string') {
try {
return new Headers(JSON.parse(str));
} catch (_) {}
let headers = str.split(';').filter(h => h !== '').reduce((ph, ch, ci) => {
const values = ch.split(':');
ph.append(values[0], values[1]);
return ph;
}, new Headers());
return headers;
}
}

// Defines a GraphQL fetcher using the fetch API.
function graphQLFetcher(endpoint) {
function graphQLFetcher(endpoint, headers = null) {
return function(graphQLParams) {
return fetch(endpoint, {
method: 'post',
headers: { 'Content-Type': 'application/json' },
headers: headers ? createHeaders(headers) : { 'Content-Type': 'application/json' },
body: JSON.stringify(graphQLParams),
credentials: 'include',
}).then(response => response.json());
Expand All @@ -67,39 +96,53 @@ class ChromeiQL extends React.Component {
this.state = {
prevEndpoint: null,
currEndpoint: this.props.endpoint,
prevHeaders: null,
currHeaders: this.props.headers,
};

this.setEndpoint = this.setEndpoint.bind(this)
this.updateEndpoint = this.updateEndpoint.bind(this)
this.setHeaders = this.setHeaders.bind(this)
this.updateHeaders = this.updateHeaders.bind(this)
}

render() {
const endpoint = this.state.currEndpoint
const headers = this.state.currHeaders
let graphqlConsole = null;
if (endpoint) {

graphqlConsole =
<GraphiQL
id = "graphiql"
fetcher = {graphQLFetcher(endpoint)}
fetcher = {graphQLFetcher(endpoint, headers)}
query = {parameters.query}
variables = {parameters.variables}
onEditQuery = {onEditQuery}
onEditVariables = {onEditVariables} />;
}

// If we have changed endpoints just now...
if (this.state.currEndpoint !== this.state.prevEndpoint) {
// then we shall re-execute the query after render
setTimeout(() => $('button.execute-button').click(), 500);
}
// If we have changed endpoints just now...
if (this.state.currHeaders !== this.state.prevHeaders) {
// then we shall re-execute the query after render
setTimeout(() => $('button.execute-button').click(), 500);
}

return (
<div id = "application">
<div id="url-bar" className="graphiql-container" >
<div id="input-bar" className="graphiql-container" >
<input type="text" id="url-box" defaultValue={endpoint} onChange={this.updateEndpoint} />
<a id="url-save-button" className="toolbar-button" onClick={this.setEndpoint}>
Set endpoint
</a>
<input type="text" id="headers-box" defaultValue={headers} onChange={this.updateHeaders} />
<a id="headers-save-button" className="toolbar-button" onClick={this.setHeaders}>
Set headers
</a>
</div>
{ graphqlConsole }
</div>
Expand Down Expand Up @@ -128,12 +171,36 @@ class ChromeiQL extends React.Component {
updateEndpoint(e) {
chromeiqlEndpoint = e.target.value;
}

setHeaders() {
const newHeaders = chromeiqlHeaders;
const setState = this.setState.bind(this);
const currState = this.state;

chrome.storage.local.set(
{ "chromeiqlHeaders": newHeaders },
() => {
if (!chrome.runtime.lastError) {
// Move current endpoint to previous, and set current endpoint to new.
setState({
prevHeaders: currState.currHeaders,
currHeaders: newHeaders
});
}
}
);
}

updateHeaders(e) {
chromeiqlHeaders = e.target.value;
}
}

chrome.storage.local.get("chromeiqlEndpoint", (storage) =>

chrome.storage.local.get(["chromeiqlEndpoint", "chromeiqlHeaders"], (storage) =>
// Render <GraphiQL /> into the body.
ReactDOM.render(
<ChromeiQL endpoint={storage.chromeiqlEndpoint} />,
<ChromeiQL endpoint={storage.chromeiqlEndpoint} headers={storage.chromeiqlHeaders} />,
document.body
)
);