@backland/schema
Version:
TypeScript schema declaration and validation library with static type inference
484 lines (483 loc) • 14.2 kB
JavaScript
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import { formatGraphQL } from '@backland/utils';
import { getByPath } from '@backland/utils';
import { hashString } from '@backland/utils';
import { isListType, isNonNullType, isObjectType, isUnionType } from 'graphql';
import { resolverKinds } from '../createGraphQLSchema';
import { LiteralField } from '../fields/LiteralField';
export function getSchemaQueryTemplates(schema) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var {
depthLimit = 5000,
includeDeprecatedFields = true
} = options;
var query = schema.getQueryType();
var mutation = schema.getMutationType();
var subscription = schema.getSubscriptionType();
var fullQuery = '';
var queryByResolver = {
mutation: {},
query: {},
subscription: {}
};
var items = [query ? {
kind: resolverKinds.query,
value: query
} : undefined, mutation ? {
kind: resolverKinds.mutation,
value: mutation
} : undefined, subscription ? {
kind: resolverKinds.subscription,
value: subscription
} : undefined].filter(Boolean);
items.forEach(item => {
if (!item) return;
var {
value,
kind
} = item;
Object.values(value.getFields()).forEach(graphQLField => {
var item = getQueryTemplates({
depthLimit,
graphQLField,
includeDeprecatedFields,
kind,
queryKind: 'mainQuery'
});
queryByResolver[kind][graphQLField.name] = item;
fullQuery += "".concat(item.fullQuery);
});
});
return {
fullQuery: fullQuery.trim(),
queryByResolver
};
}
/**
* Generate the query for the specified field
* @param params
*/
export function getQueryTemplates(params) {
var {
kind = 'query'
} = params;
var {
name
} = params.graphQLField;
var {
breadcrumb = [name],
graphQLField,
queryKind,
includeDeprecatedFields = true,
format = true
} = params;
var cache = {};
var {
payload
} = processField({
cache,
graphQLField,
includeDeprecatedFields
});
var fieldStrings = fieldsToString({
breadcrumb,
cache,
field: payload,
isTopQuery: false
});
var innerQuery = payload.isObject ? "{".concat(fieldStrings.query, "}") : '';
var fullQuery = '';
var fieldQuery = "".concat(name, " ").concat(fieldStrings.argsParsed.strings.innerArgsString, " ").concat(innerQuery);
if (queryKind === 'mainQuery') {
var {
allArgs
} = fieldStrings;
var argValues = Object.values(allArgs);
var topArgs = argValues.map(el => el.strings.topArgsStringPart).filter(Boolean);
var innerArgs = argValues.map(el => el.strings.innerArgsStringPart).filter(Boolean);
var topArgsString = topArgs.length ? "(".concat(topArgs.join(','), ")") : '';
var innerArgsString = innerArgs.length ? "(".concat(innerArgs.join(','), ")") : '';
fullQuery += "".concat(kind, " ").concat(name).concat(topArgsString, " { ").concat(name, " ").concat(innerArgsString, " ").concat(innerQuery, "}");
} else {
fullQuery += "".concat(kind, " ").concat(fieldQuery);
}
if (format) {
fullQuery = prettifyQuery(fullQuery, 'mainQuery');
fieldQuery = prettifyQuery(fieldQuery, 'fieldQuery');
}
fullQuery += "\n";
return _objectSpread(_objectSpread({}, fieldStrings), {}, {
fieldQuery,
fields: payload,
fullQuery
});
}
function getFieldPayload(_ref) {
var {
graphQLField,
cache
} = _ref;
var {
args,
type
} = graphQLField;
var {
innerType
} = getInnerType(type);
var innerTypeString = innerType.toJSON();
var {
hash: key,
readableHash
} = hashField(graphQLField);
if (cache[key]) return cache[key];
var payload = cache[key] = {
args,
children: [],
deprecationReason: getByPath(innerType, 'deprecationReason'),
description: getByPath(innerType, 'description'),
fields: {},
hash: key,
innerTypeString: innerTypeString,
isObject: false,
isUnion: false,
readableHash
};
if (isObjectType(innerType)) {
payload.isObject = true;
Object.entries(innerType.getFields()).forEach(_ref2 => {
var [name, field] = _ref2;
payload.fields[name] = getFieldPayload({
cache,
graphQLField: field
});
});
}
if (isUnionType(innerType)) {
var unionTypes = innerType.getTypes();
payload.isUnion = true;
unionTypes.forEach(unionType => {
var unionItem = getFieldPayload({
cache,
graphQLField: {
args: [],
astNode: unionType.astNode,
deprecationReason: getByPath(unionType, 'deprecationReason'),
description: unionType.description,
extensions: unionType.extensions,
name: unionType.name,
type: unionType
}
});
payload.children.push(unionItem);
});
}
return payload;
}
export function processField(config) {
var {
includeDeprecatedFields,
cache = {},
graphQLField
} = config;
var {
innerType: type
} = getInnerType(graphQLField.type);
var {
hash: key
} = hashField(graphQLField);
if (cache[key] !== undefined) {
return {
cache,
payload: cache[key]
};
}
var payload = getFieldPayload({
cache,
graphQLField
});
if (isObjectType(type)) {
var gqlTypeFields = type.getFields();
var fields = Object.entries(gqlTypeFields).filter(_ref3 => {
var [_, child] = _ref3;
return includeDeprecatedFields || !child.deprecationReason;
});
fields.forEach(_ref4 => {
var [_, field] = _ref4;
var item = getFieldPayload({
cache,
graphQLField: field
});
if (!item.isObject) {
return;
}
processField({
cache,
graphQLField: field,
includeDeprecatedFields
});
});
}
return {
cache,
payload
};
}
function fieldsToString(config) {
var {
field,
//
cache,
breadcrumb,
fieldsToStringCache = {}
} = config;
var {
fields,
args,
hash
} = field;
if (fieldsToStringCache[hash]) {
return fieldsToStringCache[hash];
}
var allArgs = config.allArgs || {};
var argsParsed = parseArgs({
args,
breadcrumb
});
allArgs[hash] = argsParsed;
var self = {
allArgs,
argsParsed,
query: ''
};
fieldsToStringCache[hash] = self;
if (field.isObject) {
Object.entries(fields || {}).forEach(_ref5 => {
var [name, field] = _ref5;
var _breadcrumb = [...breadcrumb, name];
if (!field.isObject && !field.isUnion) {
var {
argsParsed: {
strings: {
innerArgsString
}
}
} = fieldsToString({
allArgs,
breadcrumb: _breadcrumb,
cache,
field,
fieldsToStringCache,
isTopQuery: false
});
self.query += " ".concat(name).concat(innerArgsString, " ");
return;
}
if (field.isObject) {
var child = fieldsToString({
allArgs,
breadcrumb: _breadcrumb,
cache,
field,
fieldsToStringCache,
isTopQuery: false
});
var {
argsParsed: {
strings: {
innerArgsString: _innerArgsString
}
}
} = child;
self.query += " ".concat(name).concat(_innerArgsString, " { ");
self.query += child.query;
self.query += " } ";
}
if (field.isUnion) {
var childQuery = '';
var argsStrings = [];
var topArgsStrings = [];
field.children.forEach(item => {
var u_field = cache[item.hash];
var child = fieldsToString({
breadcrumb: _breadcrumb,
cache,
field: u_field,
fieldsToStringCache,
isTopQuery: false
});
var {
argsParsed: {
strings: {
innerArgsStringPart,
topArgsStringPart
}
}
} = child;
argsStrings.push(innerArgsStringPart);
topArgsStrings.push(topArgsStringPart);
childQuery += "... on ".concat(item.innerTypeString, " { ").concat(child.query, " }");
});
self.query += " ".concat(name).concat(argsStrings ? "".concat(argsStrings.join()) : '', " { ");
self.query += childQuery;
self.query += " } ";
}
});
} else {
var {
argsParsed: {
strings: {
innerArgsString
}
}
} = fieldsToString({
allArgs,
breadcrumb,
cache,
field,
fieldsToStringCache,
isTopQuery: false
});
self.query += "".concat(innerArgsString);
}
return self;
}
function parseArgs(config) {
var {
args,
breadcrumb
} = config;
var vars = [];
if (!(args !== null && args !== void 0 && args.length)) {
return {
strings: parsedArgsToString(vars),
vars
};
}
var prefix = breadcrumb.length ? breadcrumb.join('_') + '_' : '';
args.forEach(arg => {
var {
type,
description,
deprecationReason,
defaultValue,
name
} = arg;
var varName = "$".concat(prefix).concat(name);
var comments = descriptionsToComments(deprecationReason, description);
var _defaultValue = arg.defaultValue !== undefined ? LiteralField.utils.serialize(defaultValue) : undefined;
if (typeof defaultValue === 'string') {
_defaultValue = JSON.stringify(_defaultValue);
}
vars.push({
comments,
defaultValue: _defaultValue,
name,
type: type.toString(),
varName
});
});
return {
strings: parsedArgsToString(vars),
vars
};
}
function parsedArgsToString(parsed) {
var innerParts = [];
var topParts = [];
parsed.forEach(_ref6 => {
var {
type,
defaultValue,
name,
varName,
comments
} = _ref6;
topParts.push("".concat(comments).concat(varName, ": ").concat(type));
innerParts.push("".concat(comments).concat(name, ": ").concat(varName));
if (defaultValue !== undefined) {
topParts.push("= ".concat(defaultValue));
}
});
var topArgsStringPart = topParts.join(',').replace(',=', ' = ');
var innerArgsStringPart = innerParts.join(',').replace(',=', ' = ');
return {
innerArgsString: innerArgsStringPart.length ? "(".concat(innerArgsStringPart, ")") : '',
innerArgsStringPart: innerArgsStringPart,
topArgsString: topArgsStringPart.length ? "(".concat(topArgsStringPart, ")") : '',
topArgsStringPart
};
}
export function getInnerType(graphqlType) {
var wrappers = [];
while ('ofType' in graphqlType) {
if (isUnionType(graphqlType)) {
wrappers.push('union');
}
if (!isNonNullType(graphqlType)) {
wrappers.push('optional');
}
if (isListType(graphqlType)) {
wrappers.push('list');
}
graphqlType = graphqlType.ofType;
}
var wrappersPath = wrappers.join('');
var innerTypeJSON = graphqlType.toJSON();
return {
innerType: graphqlType,
innerTypeJSON,
wrappers,
wrappersPath
};
}
function hashField(graphQLField) {
var {
wrappersPath,
innerType
} = getInnerType(graphQLField.type);
var argString = '';
graphQLField.args.forEach(_ref7 => {
var {
type,
description,
deprecationReason,
defaultValue,
name
} = _ref7;
argString += [name, type.toString(), description, deprecationReason, defaultValue].filter(el => el !== null && el !== undefined).join('');
});
var suffix = "".concat(wrappersPath).concat(argString);
var hash = hashString(suffix);
return {
hash: "".concat(innerType).concat(hash),
readableHash: "".concat(innerType).concat(suffix)
};
}
function descriptionsToComments() {
for (var _len = arguments.length, list = new Array(_len), _key = 0; _key < _len; _key++) {
list[_key] = arguments[_key];
}
var commentsList = [...list].filter(Boolean);
var comments = '';
if (commentsList.length) {
return "\n#".concat(commentsList.join('\n#'), "\n");
}
return comments;
}
function prettifyQuery(value, queryKind) {
var isMainQuery = queryKind === 'mainQuery';
value = value.trim();
try {
value = formatGraphQL(isMainQuery ? value : "{".concat(value, "}"));
} catch (e) {
// throw new Error(`Failed to prettify:\n${value}\n\n\n${e.stack}`);
}
if (isMainQuery) return value;
return value.trim() //
.replace(/^{/, '').replace(/}$/, '');
}
//# sourceMappingURL=getQueryTemplates.js.map