Skip to content

Instantly share code, notes, and snippets.

@ergofriend
Created February 27, 2022 23:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ergofriend/78ca07e03d38c49a65fc3ceb00686908 to your computer and use it in GitHub Desktop.
Save ergofriend/78ca07e03d38c49a65fc3ceb00686908 to your computer and use it in GitHub Desktop.
graphql-codegen persisted-queries
"use strict";
/**
* from https://github.com/valu-digital/graphql-codegen-persisted-query-ids/blob/master/src/index.ts
* schema:
* - ./schema.graphql
* generates:
* src/generated/persisted-queries.ts:
* documents: `./src/**\/!(*.d).{ts,tsx}`
* plugins:
* - make-persist.js:
*/
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
exports.__esModule = true;
exports.plugin = exports.format = exports.generateQueryIds = exports.findFragments = exports.findUsedFragments = void 0;
var crypto = require("crypto");
var graphql_1 = require("graphql");
function createHash(s, config) {
return crypto
.createHash(config.algorithm || 'sha256')
.update(s, 'utf8')
.digest()
.toString('hex');
}
function printDefinitions(definitions) {
return definitions.map(graphql_1.print).join('\n');
}
var TYPENAME_FIELD = {
kind: graphql_1.Kind.FIELD,
name: {
kind: graphql_1.Kind.NAME,
value: '__typename'
}
};
// From apollo-client https://github.com/apollographql/apollo-client/blob/3a9dfe268979618180823eef93e96ab87468449c/packages/apollo-utilities/src/transform.ts
function addTypenameToDocument(doc) {
return (0, graphql_1.visit)(doc, {
SelectionSet: {
enter: function (node, _key, parent) {
// Don't add __typename to OperationDefinitions.
if (parent &&
parent.kind ===
'OperationDefinition') {
return;
}
// No changes if no selections.
var selections = node.selections;
if (!selections) {
return;
}
// If selections already have a __typename, or are part of an
// introspection query, do nothing.
var skip = selections.some(function (selection) {
return (selection.kind === 'Field' &&
(selection.name.value === '__typename' ||
selection.name.value.lastIndexOf('__', 0) === 0));
});
if (skip) {
return;
}
// Create and return a new SelectionSet with a __typename Field.
return __assign(__assign({}, node), { selections: __spreadArray(__spreadArray([], selections, true), [TYPENAME_FIELD], false) });
}
}
});
}
function findUsedFragments(operation, knownFragments, _usedFragments) {
var usedFragments = _usedFragments
? _usedFragments
: new Map();
(0, graphql_1.visit)(operation, {
FragmentSpread: {
enter: function (node) {
var frag = knownFragments.get(node.name.value);
if (frag) {
usedFragments.set(node.name.value, frag);
findUsedFragments(frag, knownFragments, usedFragments);
}
else {
throw new Error('Unknown fragment: ' + node.name.value);
}
}
}
});
return usedFragments;
}
exports.findUsedFragments = findUsedFragments;
function findFragments(docs) {
var fragments = new Map();
for (var _i = 0, docs_1 = docs; _i < docs_1.length; _i++) {
var doc = docs_1[_i];
(0, graphql_1.visit)(doc, {
FragmentDefinition: {
enter: function (node) {
fragments.set(node.name.value, node);
}
}
});
}
return fragments;
}
exports.findFragments = findFragments;
function generateQueryIds(docs, config) {
docs = docs.map(addTypenameToDocument);
var out = {};
var knownFragments = findFragments(docs);
var _loop_1 = function (doc) {
(0, graphql_1.visit)(doc, {
OperationDefinition: {
enter: function (def) {
if (!def.name) {
throw new Error('OperationDefinition missing name');
}
var usedFragments = findUsedFragments(def, knownFragments);
var query = printDefinitions(__spreadArray(__spreadArray([], Array.from(usedFragments.values()), true), [
def,
], false));
var hash = createHash(query, config);
var usesVariables = Boolean(def.variableDefinitions &&
def.variableDefinitions.length > 0);
out[def.name.value] = {
hash: hash,
query: query,
usesVariables: usesVariables,
loc: doc.loc
};
}
}
});
};
for (var _i = 0, docs_2 = docs; _i < docs_2.length; _i++) {
var doc = docs_2[_i];
_loop_1(doc);
}
return out;
}
exports.generateQueryIds = generateQueryIds;
exports.format = {
server: function (queries) {
var out = {};
for (var _i = 0, _a = Object.keys(queries); _i < _a.length; _i++) {
var queryName = _a[_i];
out[queries[queryName].hash] = queries[queryName].query;
}
return out;
},
client: function (queries) {
var out = {};
for (var _i = 0, _a = Object.keys(queries); _i < _a.length; _i++) {
var queryName = _a[_i];
out[queryName] = queries[queryName].hash;
}
return out;
}
};
var plugin = function (_schema, documents, config) {
var queries = generateQueryIds(documents.map(function (doc) {
// graphql-code-generator moved from .content to .document at some point.
// Try to work with both. Must use any since the tests can only have
// one version of the typings
var anyDoc = doc;
var docNode = anyDoc.content || anyDoc.document;
return docNode;
}), config);
var server = exports.format.server(queries);
var serverString = JSON.stringify(server, null, 2);
var client = exports.format.client(queries);
var clientString = JSON.stringify(client, null, 2);
return "\nexport const server = ".concat(serverString, "\nexport const client = ").concat(clientString, "\n");
};
exports.plugin = plugin;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment