@backland/schema
Version:
TypeScript schema declaration and validation library with static type inference
459 lines (458 loc) • 19 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
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 _options$depthLimit = options.depthLimit,
depthLimit = _options$depthLimit === void 0 ? 5000 : _options$depthLimit,
_options$includeDepre = options.includeDeprecatedFields,
includeDeprecatedFields = _options$includeDepre === void 0 ? true : _options$includeDepre;
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(function (item) {
if (!item) return;
var value = item.value,
kind = item.kind;
Object.values(value.getFields()).forEach(function (graphQLField) {
var item = getQueryTemplates({
depthLimit: depthLimit,
graphQLField: graphQLField,
includeDeprecatedFields: includeDeprecatedFields,
kind: kind,
queryKind: 'mainQuery'
});
queryByResolver[kind][graphQLField.name] = item;
fullQuery += "".concat(item.fullQuery);
});
});
return {
fullQuery: fullQuery.trim(),
queryByResolver: queryByResolver
};
}
/**
* Generate the query for the specified field
* @param params
*/
export function getQueryTemplates(params) {
var _params$kind = params.kind,
kind = _params$kind === void 0 ? 'query' : _params$kind;
var name = params.graphQLField.name;
var _params$breadcrumb = params.breadcrumb,
breadcrumb = _params$breadcrumb === void 0 ? [name] : _params$breadcrumb,
graphQLField = params.graphQLField,
queryKind = params.queryKind,
_params$includeDeprec = params.includeDeprecatedFields,
includeDeprecatedFields = _params$includeDeprec === void 0 ? true : _params$includeDeprec,
_params$format = params.format,
format = _params$format === void 0 ? true : _params$format;
var cache = {};
var _processField = processField({
cache: cache,
graphQLField: graphQLField,
includeDeprecatedFields: includeDeprecatedFields
}),
payload = _processField.payload;
var fieldStrings = fieldsToString({
breadcrumb: breadcrumb,
cache: 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.allArgs;
var argValues = Object.values(allArgs);
var topArgs = argValues.map(function (el) {
return el.strings.topArgsStringPart;
}).filter(Boolean);
var innerArgs = argValues.map(function (el) {
return 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: fieldQuery,
fields: payload,
fullQuery: fullQuery
});
}
function getFieldPayload(_ref) {
var graphQLField = _ref.graphQLField,
cache = _ref.cache;
var args = graphQLField.args,
type = graphQLField.type;
var _getInnerType = getInnerType(type),
innerType = _getInnerType.innerType;
var innerTypeString = innerType.toJSON();
var _hashField = hashField(graphQLField),
key = _hashField.hash,
readableHash = _hashField.readableHash;
if (cache[key]) return cache[key];
var payload = cache[key] = {
args: args,
children: [],
deprecationReason: getByPath(innerType, 'deprecationReason'),
description: getByPath(innerType, 'description'),
fields: {},
hash: key,
innerTypeString: innerTypeString,
isObject: false,
isUnion: false,
readableHash: readableHash
};
if (isObjectType(innerType)) {
payload.isObject = true;
Object.entries(innerType.getFields()).forEach(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2),
name = _ref3[0],
field = _ref3[1];
payload.fields[name] = getFieldPayload({
cache: cache,
graphQLField: field
});
});
}
if (isUnionType(innerType)) {
var unionTypes = innerType.getTypes();
payload.isUnion = true;
unionTypes.forEach(function (unionType) {
var unionItem = getFieldPayload({
cache: 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 = config.includeDeprecatedFields,
_config$cache = config.cache,
cache = _config$cache === void 0 ? {} : _config$cache,
graphQLField = config.graphQLField;
var _getInnerType2 = getInnerType(graphQLField.type),
type = _getInnerType2.innerType;
var _hashField2 = hashField(graphQLField),
key = _hashField2.hash;
if (cache[key] !== undefined) {
return {
cache: cache,
payload: cache[key]
};
}
var payload = getFieldPayload({
cache: cache,
graphQLField: graphQLField
});
if (isObjectType(type)) {
var gqlTypeFields = type.getFields();
var fields = Object.entries(gqlTypeFields).filter(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
_ = _ref5[0],
child = _ref5[1];
return includeDeprecatedFields || !child.deprecationReason;
});
fields.forEach(function (_ref6) {
var _ref7 = _slicedToArray(_ref6, 2),
_ = _ref7[0],
field = _ref7[1];
var item = getFieldPayload({
cache: cache,
graphQLField: field
});
if (!item.isObject) {
return;
}
processField({
cache: cache,
graphQLField: field,
includeDeprecatedFields: includeDeprecatedFields
});
});
}
return {
cache: cache,
payload: payload
};
}
function fieldsToString(config) {
var field = config.field,
cache = config.cache,
breadcrumb = config.breadcrumb,
_config$fieldsToStrin = config.fieldsToStringCache,
fieldsToStringCache = _config$fieldsToStrin === void 0 ? {} : _config$fieldsToStrin;
var fields = field.fields,
args = field.args,
hash = field.hash;
if (fieldsToStringCache[hash]) {
return fieldsToStringCache[hash];
}
var allArgs = config.allArgs || {};
var argsParsed = parseArgs({
args: args,
breadcrumb: breadcrumb
});
allArgs[hash] = argsParsed;
var self = {
allArgs: allArgs,
argsParsed: argsParsed,
query: ''
};
fieldsToStringCache[hash] = self;
if (field.isObject) {
Object.entries(fields || {}).forEach(function (_ref8) {
var _ref9 = _slicedToArray(_ref8, 2),
name = _ref9[0],
field = _ref9[1];
var _breadcrumb = [].concat(_toConsumableArray(breadcrumb), [name]);
if (!field.isObject && !field.isUnion) {
var _fieldsToString = fieldsToString({
allArgs: allArgs,
breadcrumb: _breadcrumb,
cache: cache,
field: field,
fieldsToStringCache: fieldsToStringCache,
isTopQuery: false
}),
innerArgsString = _fieldsToString.argsParsed.strings.innerArgsString;
self.query += " ".concat(name).concat(innerArgsString, " ");
return;
}
if (field.isObject) {
var child = fieldsToString({
allArgs: allArgs,
breadcrumb: _breadcrumb,
cache: cache,
field: field,
fieldsToStringCache: fieldsToStringCache,
isTopQuery: false
});
var _innerArgsString = child.argsParsed.strings.innerArgsString;
self.query += " ".concat(name).concat(_innerArgsString, " { ");
self.query += child.query;
self.query += " } ";
}
if (field.isUnion) {
var childQuery = '';
var argsStrings = [];
var topArgsStrings = [];
field.children.forEach(function (item) {
var u_field = cache[item.hash];
var child = fieldsToString({
breadcrumb: _breadcrumb,
cache: cache,
field: u_field,
fieldsToStringCache: fieldsToStringCache,
isTopQuery: false
});
var _child$argsParsed$str = child.argsParsed.strings,
innerArgsStringPart = _child$argsParsed$str.innerArgsStringPart,
topArgsStringPart = _child$argsParsed$str.topArgsStringPart;
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 _fieldsToString2 = fieldsToString({
allArgs: allArgs,
breadcrumb: breadcrumb,
cache: cache,
field: field,
fieldsToStringCache: fieldsToStringCache,
isTopQuery: false
}),
innerArgsString = _fieldsToString2.argsParsed.strings.innerArgsString;
self.query += "".concat(innerArgsString);
}
return self;
}
function parseArgs(config) {
var args = config.args,
breadcrumb = config.breadcrumb;
var vars = [];
if (!(args !== null && args !== void 0 && args.length)) {
return {
strings: parsedArgsToString(vars),
vars: vars
};
}
var prefix = breadcrumb.length ? breadcrumb.join('_') + '_' : '';
args.forEach(function (arg) {
var type = arg.type,
description = arg.description,
deprecationReason = arg.deprecationReason,
defaultValue = arg.defaultValue,
name = arg.name;
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: comments,
defaultValue: _defaultValue,
name: name,
type: type.toString(),
varName: varName
});
});
return {
strings: parsedArgsToString(vars),
vars: vars
};
}
function parsedArgsToString(parsed) {
var innerParts = [];
var topParts = [];
parsed.forEach(function (_ref10) {
var type = _ref10.type,
defaultValue = _ref10.defaultValue,
name = _ref10.name,
varName = _ref10.varName,
comments = _ref10.comments;
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: 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: innerTypeJSON,
wrappers: wrappers,
wrappersPath: wrappersPath
};
}
function hashField(graphQLField) {
var _getInnerType3 = getInnerType(graphQLField.type),
wrappersPath = _getInnerType3.wrappersPath,
innerType = _getInnerType3.innerType;
var argString = '';
graphQLField.args.forEach(function (_ref11) {
var type = _ref11.type,
description = _ref11.description,
deprecationReason = _ref11.deprecationReason,
defaultValue = _ref11.defaultValue,
name = _ref11.name;
argString += [name, type.toString(), description, deprecationReason, defaultValue].filter(function (el) {
return 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 = [].concat(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