123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- // @flow strict
- import type { FormattedExecutionResult } from 'graphql';
- export type GraphiQLData = {|
- query?: string | null,
- variables?: { +[name: string]: mixed, ... } | null,
- operationName?: string | null,
- result?: FormattedExecutionResult,
- |};
- export type GraphiQLOptions = {|
- /**
- * An optional GraphQL string to use when no query is provided and no stored
- * query exists from a previous session. If undefined is provided, GraphiQL
- * will use its own default query.
- */
- defaultQuery?: string,
- /**
- * An optional boolean which enables the header editor when true.
- * Defaults to false.
- */
- headerEditorEnabled?: boolean,
- |};
- // Ensures string values are safe to be used within a <script> tag.
- function safeSerialize(data: string | boolean | null | void): string {
- return data != null
- ? JSON.stringify(data).replace(/\//g, '\\/')
- : 'undefined';
- }
- // Implemented as Babel transformation, see ../resources/load-statically-from-npm.js
- declare function loadFileStaticallyFromNPM(npmPath: string): string;
- /**
- * When express-graphql receives a request which does not Accept JSON, but does
- * Accept HTML, it may present GraphiQL, the in-browser GraphQL explorer IDE.
- *
- * When shown, it will be pre-populated with the result of having executed the
- * requested query.
- */
- export function renderGraphiQL(
- data: GraphiQLData,
- options?: GraphiQLOptions,
- ): string {
- const queryString = data.query;
- const variablesString =
- data.variables != null ? JSON.stringify(data.variables, null, 2) : null;
- const resultString =
- data.result != null ? JSON.stringify(data.result, null, 2) : null;
- const operationName = data.operationName;
- const defaultQuery = options?.defaultQuery;
- const headerEditorEnabled = options?.headerEditorEnabled;
- return `<!--
- The request to this GraphQL server provided the header "Accept: text/html"
- and as a result has been presented GraphiQL - an in-browser IDE for
- exploring GraphQL.
- If you wish to receive JSON, provide the header "Accept: application/json" or
- add "&raw" to the end of the URL within a browser.
- -->
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- <title>GraphiQL</title>
- <meta name="robots" content="noindex" />
- <meta name="referrer" content="origin" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style>
- body {
- margin: 0;
- overflow: hidden;
- }
- #graphiql {
- height: 100vh;
- }
- </style>
- <style>
- /* graphiql/graphiql.css */
- ${loadFileStaticallyFromNPM('graphiql/graphiql.css')}
- </style>
- <script>
- // promise-polyfill/dist/polyfill.min.js
- ${loadFileStaticallyFromNPM('promise-polyfill/dist/polyfill.min.js')}
- </script>
- <script>
- // unfetch/dist/unfetch.umd.js
- ${loadFileStaticallyFromNPM('unfetch/dist/unfetch.umd.js')}
- </script>
- <script>
- // react/umd/react.production.min.js
- ${loadFileStaticallyFromNPM('react/umd/react.production.min.js')}
- </script>
- <script>
- // react-dom/umd/react-dom.production.min.js
- ${loadFileStaticallyFromNPM('react-dom/umd/react-dom.production.min.js')}
- </script>
- <script>
- // graphiql/graphiql.min.js
- ${loadFileStaticallyFromNPM('graphiql/graphiql.min.js')}
- </script>
- </head>
- <body>
- <div id="graphiql">Loading...</div>
- <script>
- // Collect the URL parameters
- var parameters = {};
- window.location.search.substr(1).split('&').forEach(function (entry) {
- var eq = entry.indexOf('=');
- if (eq >= 0) {
- parameters[decodeURIComponent(entry.slice(0, eq))] =
- decodeURIComponent(entry.slice(eq + 1));
- }
- });
- // Produce a Location query string from a parameter object.
- function locationQuery(params) {
- return '?' + Object.keys(params).filter(function (key) {
- return Boolean(params[key]);
- }).map(function (key) {
- return encodeURIComponent(key) + '=' +
- encodeURIComponent(params[key]);
- }).join('&');
- }
- // Derive a fetch URL from the current URL, sans the GraphQL parameters.
- var graphqlParamNames = {
- query: true,
- variables: true,
- operationName: true
- };
- var otherParams = {};
- for (var k in parameters) {
- if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
- otherParams[k] = parameters[k];
- }
- }
- var fetchURL = locationQuery(otherParams);
- // Defines a GraphQL fetcher using the fetch API.
- function graphQLFetcher(graphQLParams, opts) {
- return fetch(fetchURL, {
- method: 'post',
- headers: Object.assign(
- {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json'
- },
- opts && opts.headers,
- ),
- body: JSON.stringify(graphQLParams),
- credentials: 'include',
- }).then(function (response) {
- return response.json();
- });
- }
- // When the query and variables string is edited, update the URL bar so
- // that it can be easily shared.
- function onEditQuery(newQuery) {
- parameters.query = newQuery;
- updateURL();
- }
- function onEditVariables(newVariables) {
- parameters.variables = newVariables;
- updateURL();
- }
- function onEditOperationName(newOperationName) {
- parameters.operationName = newOperationName;
- updateURL();
- }
- function updateURL() {
- history.replaceState(null, null, locationQuery(parameters));
- }
- // Render <GraphiQL /> into the body.
- ReactDOM.render(
- React.createElement(GraphiQL, {
- fetcher: graphQLFetcher,
- onEditQuery: onEditQuery,
- onEditVariables: onEditVariables,
- onEditOperationName: onEditOperationName,
- query: ${safeSerialize(queryString)},
- response: ${safeSerialize(resultString)},
- variables: ${safeSerialize(variablesString)},
- operationName: ${safeSerialize(operationName)},
- defaultQuery: ${safeSerialize(defaultQuery)},
- headerEditorEnabled: ${safeSerialize(headerEditorEnabled)},
- }),
- document.getElementById('graphiql')
- );
- </script>
- </body>
- </html>`;
- }
|