graphiql-code-exporter
Version:
Export working code snippets from GraphiQL queries
182 lines (145 loc) • 9.25 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
import capitalizeFirstLetter from '../../utils/capitalizeFirstLetter';
import commentsFactory from '../../utils/jsCommentsFactory.js';
import { isOperationNamed, collapseExtraNewlines, addLeftWhitespace } from '../../utils';
import 'codemirror/mode/javascript/javascript';
var snippetOptions = [{
id: 'server',
label: 'server-side usage',
initial: false
}, {
id: 'asyncAwait',
label: 'async/await',
initial: true
}];
var comments = {
setup: 'This setup is only needed once per application',
nodeFetch: 'Node doesn\'t implement fetch so we have to import it',
graphqlError: 'handle those errors like a pro',
graphqlData: 'do something great with this precious data',
fetchError: 'handle errors from fetch itself'
};
function generateDocumentQuery(operationDataList) {
var body = operationDataList.map(function (operationData) {
return operationData.query;
}).join('\n\n').trim();
return 'const operationsDoc = `\n' + addLeftWhitespace(body, 2) + '\n`;';
}
var fetcherName = 'fetchGraphQL';
function operationFunctionName(operationData) {
var type = operationData.type;
var prefix = type === 'query' ? 'fetch' : type === 'mutation' ? 'execute' : type === 'subscription' ? 'subscribeTo' : '';
var fnName = prefix + (prefix.length > 0 ? capitalizeFirstLetter(operationData.name) : operationData.name);
return fnName;
}
// Promise-based functions
function promiseFetcher(serverUrl, headers) {
return 'function ' + fetcherName + '(operationsDoc, operationName, variables) {\n return fetch(\n "' + serverUrl + '",\n {\n method: "POST",' + (headers ? '\n headers: {\n' + addLeftWhitespace(headers, 8) + '\n },' : '') + '\n body: JSON.stringify({\n query: operationsDoc,\n variables: variables,\n operationName: operationName\n })\n }\n ).then((result) => result.json());\n}';
}
function fetcherFunctions(operationDataList) {
return operationDataList.map(function (operationData) {
var fnName = operationFunctionName(operationData);
var params = (operationData.operationDefinition.variableDefinitions || []).map(function (def) {
return def.variable.name.value;
});
var variablesBody = params.map(function (param) {
return '"' + param + '": ' + param;
}).join(', ');
var variables = '{' + variablesBody + '}';
return 'function ' + fnName + '(' + params.join(', ') + ') {\n return ' + fetcherName + '(\n operationsDoc,\n "' + operationData.name + '",\n ' + variables + '\n );\n}';
}).join('\n\n');
}
function promiseFetcherInvocation(getComment, operationDataList, vars) {
return operationDataList.map(function (namedOperationData) {
var params = (namedOperationData.operationDefinition.variableDefinitions || []).map(function (def) {
return def.variable.name.value;
});
var variables = Object.entries(namedOperationData.variables || {}).map(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
key = _ref2[0],
value = _ref2[1];
return 'const ' + key + ' = ' + JSON.stringify(value, null, 2) + ';';
});
return variables.join('\n') + '\n\n' + operationFunctionName(namedOperationData) + '(' + params.join(', ') + ')\n .then(({ data, errors }) => {\n if (errors) {\n ' + getComment('graphqlError') + '\n console.error(errors);\n }\n ' + getComment('graphqlData') + '\n console.log(data);\n })\n .catch((error) => {\n ' + getComment('fetchError') + '\n console.error(error);\n });';
}).join('\n\n');
}
// Async-await-based functions
function asyncFetcher(serverUrl, headers) {
return 'async function ' + fetcherName + '(operationsDoc, operationName, variables) {\n const result = await fetch(\n "' + serverUrl + '",\n {\n method: "POST",' + (headers ? '\n headers: {\n' + addLeftWhitespace(headers, 8) + '\n },' : '') + '\n body: JSON.stringify({\n query: operationsDoc,\n variables: variables,\n operationName: operationName\n })\n }\n );\n\n return await result.json();\n}';
}
function asyncFetcherInvocation(getComment, operationDataList, vars) {
return operationDataList.map(function (namedOperationData) {
var params = (namedOperationData.operationDefinition.variableDefinitions || []).map(function (def) {
return def.variable.name.value;
});
var variables = Object.entries(namedOperationData.variables || {}).map(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
key = _ref4[0],
value = _ref4[1];
return 'const ' + key + ' = ' + JSON.stringify(value, null, 2) + ';';
});
return 'async function start' + capitalizeFirstLetter(operationFunctionName(namedOperationData)) + '(' + params.join(', ') + ') {\n const { errors, data } = await ' + operationFunctionName(namedOperationData) + '(' + params.join(', ') + ');\n\n if (errors) {\n ' + getComment('graphqlError') + '\n console.error(errors);\n }\n\n ' + getComment('graphqlData') + '\n console.log(data);\n}\n\n' + variables.join('\n') + '\n\nstart' + capitalizeFirstLetter(operationFunctionName(namedOperationData)) + '(' + params.join(', ') + ');';
}).join('\n\n');
}
// Snippet generation!
var snippet = {
language: 'JavaScript',
codeMirrorMode: 'javascript',
name: 'fetch',
options: snippetOptions,
generate: function generate(opts) {
var serverUrl = opts.serverUrl,
headers = opts.headers,
options = opts.options;
var operationDataList = opts.operationDataList.map(function (operationData, idx) {
if (!isOperationNamed(operationData)) {
return _extends({}, operationData, {
name: ('unnamed' + capitalizeFirstLetter(operationData.type) + (idx + 1)).trim(),
query: '# Consider giving this ' + operationData.type + ' a unique, descriptive\n# name in your application as a best practice\n' + operationData.type + ' unnamed' + capitalizeFirstLetter(operationData.type) + (idx + 1) + ' ' + operationData.query.trim().replace(/^(query|mutation|subscription) /i, '')
});
} else {
return operationData;
}
});
var getComment = commentsFactory(true, comments);
var serverComment = options.server ? getComment('nodeFetch') : '';
var serverImport = options.server ? 'import fetch from "node-fetch";\n' : '';
var graphqlQuery = generateDocumentQuery(operationDataList);
var vars = JSON.stringify({}, null, 2);
var headersValues = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = Object.keys(headers)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var header = _step.value;
if (header && headers[header]) {
headersValues.push('"' + header + '": "' + headers[header] + '"');
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var heads = headersValues.length ? '' + headersValues.join(',\n') : '';
var requiredDeps = [options.server ? '"node-fetch": "^2.5.0"' : null].filter(Boolean);
var packageDeps = requiredDeps.length > 0 ? '/*\nAdd these to your `package.json`:\n' + addLeftWhitespace(requiredDeps.join(',\n'), 2) + '\n*/\n' : '';
var fetcher = options.asyncAwait ? asyncFetcher(serverUrl, heads) : promiseFetcher(serverUrl, heads);
var fetcherFunctionsDefs = fetcherFunctions(operationDataList);
var fetcherInvocation = options.asyncAwait ? asyncFetcherInvocation(getComment, operationDataList, vars) : promiseFetcherInvocation(getComment, operationDataList, vars);
var snippet = '\n/*\nThis is an example snippet - you should consider tailoring it\nto your service.\n*/\n' + packageDeps + '\n' + serverComment + '\n' + serverImport + '\n\n' + fetcher + '\n\n' + graphqlQuery + '\n\n' + fetcherFunctionsDefs + '\n\n' + fetcherInvocation;
return collapseExtraNewlines(snippet.trim());
}
};
export default snippet;