UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

484 lines (483 loc) 14.2 kB
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