graphql-parse-resolve-info
Advanced tools
Comparing version 4.0.0-rc.4 to 4.0.0-rc.6
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.getAlias = exports.simplify = exports.parse = undefined; | ||
exports.getAliasFromResolveInfo = getAliasFromResolveInfo; | ||
exports.parseResolveInfo = parseResolveInfo; | ||
exports.simplifyParsedResolveInfoFragmentWithType = simplifyParsedResolveInfoFragmentWithType; | ||
var _assert = require("assert"); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _values = require("graphql/execution/values"); | ||
var _graphql = require("graphql"); | ||
var _debug = require("debug"); | ||
var _debug2 = _interopRequireDefault(_debug); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const debug = (0, _debug2.default)("graphql-parse-resolve-info"); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const assert = require("assert"); | ||
const graphql_1 = require("graphql"); | ||
// tslint:disable-next-line | ||
const values_1 = require("graphql/execution/values"); | ||
const debugFactory = require("debug"); | ||
const debug = debugFactory("graphql-parse-resolve-info"); | ||
function getArgVal(resolveInfo, argument) { | ||
if (argument.kind === "Variable") { | ||
return resolveInfo.variableValues[argument.name.value]; | ||
} else if (argument.kind === "BooleanValue") { | ||
return argument.value; | ||
} | ||
if (argument.kind === "Variable") { | ||
return resolveInfo.variableValues[argument.name.value]; | ||
} | ||
else if (argument.kind === "BooleanValue") { | ||
return argument.value; | ||
} | ||
} | ||
function skipField(resolveInfo, { directives = [] }) { | ||
let skip = false; | ||
directives.forEach(directive => { | ||
const directiveName = directive.name.value; | ||
if (Array.isArray(directive.arguments)) { | ||
const ifArgumentAst = directive.arguments.find(arg => arg.name && arg.name.value === "if"); | ||
if (ifArgumentAst) { | ||
const argumentValueAst = ifArgumentAst.value; | ||
if (directiveName === "skip") { | ||
skip = skip || getArgVal(resolveInfo, argumentValueAst); | ||
} else if (directiveName === "include") { | ||
skip = skip || !getArgVal(resolveInfo, argumentValueAst); | ||
let skip = false; | ||
directives.forEach(directive => { | ||
const directiveName = directive.name.value; | ||
if (Array.isArray(directive.arguments)) { | ||
const ifArgumentAst = directive.arguments.find(arg => arg.name && arg.name.value === "if"); | ||
if (ifArgumentAst) { | ||
const argumentValueAst = ifArgumentAst.value; | ||
if (directiveName === "skip") { | ||
skip = skip || getArgVal(resolveInfo, argumentValueAst); | ||
} | ||
else if (directiveName === "include") { | ||
skip = skip || !getArgVal(resolveInfo, argumentValueAst); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
return skip; | ||
}); | ||
return skip; | ||
} | ||
// Originally based on https://github.com/tjmehta/graphql-parse-fields | ||
function getAliasFromResolveInfo(resolveInfo) { | ||
const asts = resolveInfo.fieldNodes || resolveInfo.fieldASTs; | ||
for (let i = 0, l = asts.length; i < l; i++) { | ||
const val = asts[i]; | ||
if (val.kind === "Field") { | ||
const alias = val.alias ? val.alias.value : val.name && val.name.value; | ||
if (alias) { | ||
return alias; | ||
} | ||
const asts = resolveInfo.fieldNodes || resolveInfo.fieldASTs; | ||
for (let i = 0, l = asts.length; i < l; i++) { | ||
const val = asts[i]; | ||
if (val.kind === "Field") { | ||
const alias = val.alias ? val.alias.value : val.name && val.name.value; | ||
if (alias) { | ||
return alias; | ||
} | ||
} | ||
} | ||
} | ||
throw new Error("Could not determine alias?!"); | ||
throw new Error("Could not determine alias?!"); | ||
} | ||
exports.getAliasFromResolveInfo = getAliasFromResolveInfo; | ||
function parseResolveInfo(resolveInfo, options = {}) { | ||
const fieldNodes = resolveInfo.fieldNodes || resolveInfo.fieldASTs; | ||
const { parentType } = resolveInfo; | ||
if (!fieldNodes) { | ||
throw new Error("No fieldNodes provided!"); | ||
} | ||
if (options.keepRoot == null) { | ||
options.keepRoot = false; | ||
} | ||
if (options.deep == null) { | ||
options.deep = true; | ||
} | ||
let tree = fieldTreeFromAST(fieldNodes, resolveInfo, undefined, options, parentType); | ||
if (!options.keepRoot) { | ||
const typeKey = firstKey(tree); | ||
if (!typeKey) { | ||
return null; | ||
const fieldNodes = resolveInfo.fieldNodes || resolveInfo.fieldASTs; | ||
const { parentType } = resolveInfo; | ||
if (!fieldNodes) { | ||
throw new Error("No fieldNodes provided!"); | ||
} | ||
tree = tree[typeKey]; | ||
const fieldKey = firstKey(tree); | ||
if (!fieldKey) { | ||
return null; | ||
if (options.keepRoot == null) { | ||
options.keepRoot = false; | ||
} | ||
tree = tree[fieldKey]; | ||
} | ||
return tree; | ||
if (options.deep == null) { | ||
options.deep = true; | ||
} | ||
const tree = fieldTreeFromAST(fieldNodes, resolveInfo, undefined, options, parentType); | ||
if (!options.keepRoot) { | ||
const typeKey = firstKey(tree); | ||
if (!typeKey) { | ||
return null; | ||
} | ||
const fields = tree[typeKey]; | ||
const fieldKey = firstKey(fields); | ||
if (!fieldKey) { | ||
return null; | ||
} | ||
return fields[fieldKey]; | ||
} | ||
return tree; | ||
} | ||
exports.parseResolveInfo = parseResolveInfo; | ||
function getFieldFromAST(ast, parentType) { | ||
if (ast.kind === "Field") { | ||
const fieldNode = ast; | ||
const fieldName = fieldNode.name.value; | ||
if (!(parentType instanceof _graphql.GraphQLUnionType)) { | ||
const type = parentType; | ||
return type.getFields()[fieldName]; | ||
} else { | ||
// XXX: TODO: Handle GraphQLUnionType | ||
if (ast.kind === "Field") { | ||
const fieldNode = ast; | ||
const fieldName = fieldNode.name.value; | ||
if (!(parentType instanceof graphql_1.GraphQLUnionType)) { | ||
const type = parentType; | ||
return type.getFields()[fieldName]; | ||
} | ||
else { | ||
// XXX: TODO: Handle GraphQLUnionType | ||
} | ||
} | ||
} | ||
return; | ||
return undefined; | ||
} | ||
let iNum = 1; | ||
function fieldTreeFromAST(inASTs, resolveInfo, initTree = {}, options = {}, parentType, depth = "") { | ||
const instance = iNum++; | ||
debug("%s[%d] Entering fieldTreeFromAST with parent type '%s'", depth, instance, parentType); | ||
let { variableValues } = resolveInfo; | ||
const fragments = resolveInfo.fragments || {}; | ||
const asts = Array.isArray(inASTs) ? inASTs : [inASTs]; | ||
initTree[parentType.name] = initTree[parentType.name] || {}; | ||
const outerDepth = depth; | ||
return asts.reduce(function (tree, selectionVal, idx) { | ||
const depth = `${outerDepth} `; | ||
debug("%s[%d] Processing AST %d of %d; kind = %s", depth, instance, idx + 1, asts.length, selectionVal.kind); | ||
if (skipField(resolveInfo, selectionVal)) { | ||
debug("%s[%d] IGNORING due to directive", depth, instance); | ||
} else if (selectionVal.kind === "Field") { | ||
const val = selectionVal; | ||
const name = val.name && val.name.value; | ||
const isReserved = name && name !== "__id" && name.substr(0, 2) === "__"; | ||
if (isReserved) { | ||
debug("%s[%d] IGNORING because field '%s' is reserved", depth, instance, name); | ||
} else { | ||
const alias = val.alias && val.alias.value ? val.alias.value : val.name.value; | ||
debug("%s[%d] Field '%s' (alias = '%s')", depth, instance, name, alias); | ||
const field = getFieldFromAST(val, parentType); | ||
if (!field) { | ||
return tree; | ||
const instance = iNum++; | ||
debug("%s[%d] Entering fieldTreeFromAST with parent type '%s'", depth, instance, parentType); | ||
const { variableValues } = resolveInfo; | ||
const fragments = resolveInfo.fragments || {}; | ||
const asts = Array.isArray(inASTs) ? inASTs : [inASTs]; | ||
initTree[parentType.name] = initTree[parentType.name] || {}; | ||
const outerDepth = depth; | ||
return asts.reduce((tree, selectionVal, idx) => { | ||
// tslint:disable-next-line no-shadowed-variable | ||
const depth = `${outerDepth} `; | ||
debug("%s[%d] Processing AST %d of %d; kind = %s", depth, instance, idx + 1, asts.length, selectionVal.kind); | ||
if (skipField(resolveInfo, selectionVal)) { | ||
debug("%s[%d] IGNORING due to directive", depth, instance); | ||
} | ||
const fieldGqlType = (0, _graphql.getNamedType)(field.type); | ||
if (!fieldGqlType) { | ||
return tree; | ||
else if (selectionVal.kind === "Field") { | ||
const val = selectionVal; | ||
const name = val.name && val.name.value; | ||
const isReserved = name && name !== "__id" && name.substr(0, 2) === "__"; | ||
if (isReserved) { | ||
debug("%s[%d] IGNORING because field '%s' is reserved", depth, instance, name); | ||
} | ||
else { | ||
const alias = val.alias && val.alias.value ? val.alias.value : val.name.value; | ||
debug("%s[%d] Field '%s' (alias = '%s')", depth, instance, name, alias); | ||
const field = getFieldFromAST(val, parentType); | ||
if (!field) { | ||
return tree; | ||
} | ||
const fieldGqlTypeOrUndefined = graphql_1.getNamedType(field.type); | ||
if (!fieldGqlTypeOrUndefined) { | ||
return tree; | ||
} | ||
const fieldGqlType = fieldGqlTypeOrUndefined; | ||
const args = values_1.getArgumentValues(field, val, variableValues) || {}; | ||
if (parentType.name && !tree[parentType.name][alias]) { | ||
const newTreeRoot = { | ||
name, | ||
alias, | ||
args, | ||
fieldsByTypeName: graphql_1.isCompositeType(fieldGqlType) | ||
? { | ||
[fieldGqlType.name]: {}, | ||
} | ||
: {}, | ||
}; | ||
tree[parentType.name][alias] = newTreeRoot; | ||
} | ||
const selectionSet = val.selectionSet; | ||
if (selectionSet != null && | ||
options.deep && | ||
graphql_1.isCompositeType(fieldGqlType)) { | ||
const newParentType = fieldGqlType; | ||
debug("%s[%d] Recursing into subfields", depth, instance); | ||
fieldTreeFromAST(selectionSet.selections, resolveInfo, tree[parentType.name][alias].fieldsByTypeName, options, newParentType, `${depth} `); | ||
} | ||
else { | ||
// No fields to add | ||
debug("%s[%d] Exiting (no fields to add)", depth, instance); | ||
} | ||
} | ||
} | ||
const args = (0, _values.getArgumentValues)(field, val, variableValues) || {}; | ||
if (parentType.name && !tree[parentType.name][alias]) { | ||
const newTreeRoot = { | ||
name, | ||
alias, | ||
args, | ||
fieldsByTypeName: (0, _graphql.isCompositeType)(fieldGqlType) ? { | ||
[fieldGqlType.name]: {} | ||
} : {} | ||
}; | ||
tree[parentType.name][alias] = newTreeRoot; | ||
else if (selectionVal.kind === "FragmentSpread" && options.deep) { | ||
const val = selectionVal; | ||
const name = val.name && val.name.value; | ||
debug("%s[%d] Fragment spread '%s'", depth, instance, name); | ||
const fragment = fragments[name]; | ||
assert(fragment, 'unknown fragment "' + name + '"'); | ||
let fragmentType = parentType; | ||
if (fragment.typeCondition) { | ||
fragmentType = getType(resolveInfo, fragment.typeCondition); | ||
} | ||
if (fragmentType && graphql_1.isCompositeType(fragmentType)) { | ||
const newParentType = fragmentType; | ||
fieldTreeFromAST(fragment.selectionSet.selections, resolveInfo, tree, options, newParentType, `${depth} `); | ||
} | ||
} | ||
const selectionSet = val.selectionSet; | ||
if (selectionSet != null && options.deep && (0, _graphql.isCompositeType)(fieldGqlType)) { | ||
const newParentType = fieldGqlType; | ||
debug("%s[%d] Recursing into subfields", depth, instance); | ||
fieldTreeFromAST(selectionSet.selections, resolveInfo, tree[parentType.name][alias].fieldsByTypeName, options, newParentType, `${depth} `); | ||
} else { | ||
// No fields to add | ||
debug("%s[%d] Exiting (no fields to add)", depth, instance); | ||
else if (selectionVal.kind === "InlineFragment" && options.deep) { | ||
const val = selectionVal; | ||
const fragment = val; | ||
let fragmentType = parentType; | ||
if (fragment.typeCondition) { | ||
fragmentType = getType(resolveInfo, fragment.typeCondition); | ||
} | ||
debug("%s[%d] Inline fragment (parent = '%s', type = '%s')", depth, instance, parentType, fragmentType); | ||
if (fragmentType && graphql_1.isCompositeType(fragmentType)) { | ||
const newParentType = fragmentType; | ||
fieldTreeFromAST(fragment.selectionSet.selections, resolveInfo, tree, options, newParentType, `${depth} `); | ||
} | ||
} | ||
} | ||
} else if (selectionVal.kind === "FragmentSpread" && options.deep) { | ||
const val = selectionVal; | ||
const name = val.name && val.name.value; | ||
debug("%s[%d] Fragment spread '%s'", depth, instance, name); | ||
const fragment = fragments[name]; | ||
(0, _assert2.default)(fragment, 'unknown fragment "' + name + '"'); | ||
let fragmentType = parentType; | ||
if (fragment.typeCondition) { | ||
fragmentType = getType(resolveInfo, fragment.typeCondition); | ||
} | ||
if (fragmentType && (0, _graphql.isCompositeType)(fragmentType)) { | ||
const newParentType = fragmentType; | ||
fieldTreeFromAST(fragment.selectionSet.selections, resolveInfo, tree, options, newParentType, `${depth} `); | ||
} | ||
} else if (selectionVal.kind === "InlineFragment" && options.deep) { | ||
const val = selectionVal; | ||
const fragment = val; | ||
let fragmentType = parentType; | ||
if (fragment.typeCondition) { | ||
fragmentType = getType(resolveInfo, fragment.typeCondition); | ||
} | ||
debug("%s[%d] Inline fragment (parent = '%s', type = '%s')", depth, instance, parentType, fragmentType); | ||
if (fragmentType && (0, _graphql.isCompositeType)(fragmentType)) { | ||
const newParentType = fragmentType; | ||
fieldTreeFromAST(fragment.selectionSet.selections, resolveInfo, tree, options, newParentType, `${depth} `); | ||
} | ||
} else { | ||
debug("%s[%d] IGNORING because kind '%s' not understood", depth, instance, selectionVal.kind); | ||
} | ||
// Ref: https://github.com/graphile/postgraphile/pull/342/files#diff-d6702ec9fed755c88b9d70b430fda4d8R148 | ||
return tree; | ||
}, initTree); | ||
else { | ||
debug("%s[%d] IGNORING because kind '%s' not understood", depth, instance, selectionVal.kind); | ||
} | ||
// Ref: https://github.com/graphile/postgraphile/pull/342/files#diff-d6702ec9fed755c88b9d70b430fda4d8R148 | ||
return tree; | ||
}, initTree); | ||
} | ||
function firstKey(obj) { | ||
for (const key in obj) { | ||
return key; | ||
} | ||
for (const key in obj) { | ||
if (Object.prototype.hasOwnProperty.call(obj, key)) { | ||
return key; | ||
} | ||
} | ||
} | ||
function getType(resolveInfo, typeCondition) { | ||
const { schema } = resolveInfo; | ||
const { kind, name } = typeCondition; | ||
if (kind === "NamedType") { | ||
const typeName = name.value; | ||
return schema.getType(typeName); | ||
} | ||
const { schema } = resolveInfo; | ||
const { kind, name } = typeCondition; | ||
if (kind === "NamedType") { | ||
const typeName = name.value; | ||
return schema.getType(typeName); | ||
} | ||
} | ||
function simplifyParsedResolveInfoFragmentWithType(parsedResolveInfoFragment, Type) { | ||
const { fieldsByTypeName } = parsedResolveInfoFragment; | ||
const fields = {}; | ||
const StrippedType = (0, _graphql.getNamedType)(Type); | ||
if ((0, _graphql.isCompositeType)(StrippedType)) { | ||
Object.assign(fields, fieldsByTypeName[StrippedType.name]); | ||
if (StrippedType instanceof _graphql.GraphQLObjectType) { | ||
const ObjectType = StrippedType; | ||
// GraphQL ensures that the subfields cannot clash, so it's safe to simply overwrite them | ||
for (const Interface of ObjectType.getInterfaces()) { | ||
Object.assign(fields, fieldsByTypeName[Interface.name]); | ||
} | ||
function simplifyParsedResolveInfoFragmentWithType(parsedResolveInfoFragment, type) { | ||
const { fieldsByTypeName } = parsedResolveInfoFragment; | ||
const fields = {}; | ||
const strippedType = graphql_1.getNamedType(type); | ||
if (graphql_1.isCompositeType(strippedType)) { | ||
Object.assign(fields, fieldsByTypeName[strippedType.name]); | ||
if (strippedType instanceof graphql_1.GraphQLObjectType) { | ||
const objectType = strippedType; | ||
// GraphQL ensures that the subfields cannot clash, so it's safe to simply overwrite them | ||
for (const anInterface of objectType.getInterfaces()) { | ||
Object.assign(fields, fieldsByTypeName[anInterface.name]); | ||
} | ||
} | ||
} | ||
} | ||
return Object.assign({}, parsedResolveInfoFragment, { | ||
fields | ||
}); | ||
return Object.assign({}, parsedResolveInfoFragment, { fields }); | ||
} | ||
const parse = exports.parse = parseResolveInfo; | ||
const simplify = exports.simplify = simplifyParsedResolveInfoFragmentWithType; | ||
const getAlias = exports.getAlias = getAliasFromResolveInfo; | ||
exports.simplifyParsedResolveInfoFragmentWithType = simplifyParsedResolveInfoFragmentWithType; | ||
exports.parse = parseResolveInfo; | ||
exports.simplify = simplifyParsedResolveInfoFragmentWithType; | ||
exports.getAlias = getAliasFromResolveInfo; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "graphql-parse-resolve-info", | ||
"version": "4.0.0-rc.4", | ||
"version": "4.0.0-rc.6", | ||
"description": "Parse GraphQLResolveInfo (the 4th argument of resolve) into a simple tree", | ||
"main": "node8plus/index.js", | ||
"types": "node8plus/index.d.ts", | ||
"scripts": { | ||
"test": "jest", | ||
"prepack": "mkdir -p node8plus && babel -s true --out-dir node8plus src && flow-copy-source src node8plus", | ||
"watch": "mkdir -p node8plus && babel -s true --watch --out-dir node8plus src" | ||
"prepack": "mkdir -p node8plus && tsc", | ||
"tslint": "prettier --list-different 'src/**/*' && tslint --config ../../tslint.json --project tsconfig.json", | ||
"watch": "mkdir -p node8plus && tsc --watch" | ||
}, | ||
@@ -32,11 +34,16 @@ "repository": { | ||
"devDependencies": { | ||
"@types/debug": "0.0.30", | ||
"@types/jest": "23.3.1", | ||
"@types/node": "10.7.1", | ||
"babel-cli": "^6.24.1", | ||
"eslint_d": "5.3.1", | ||
"flow-copy-source": "^1.2.0", | ||
"jest": "^20.0.4" | ||
"jest": "23.5.0", | ||
"ts-jest": "23.1.3", | ||
"ts-node": "7.0.1", | ||
"tslint": "5.11.0", | ||
"tslint-config-prettier": "1.14.0", | ||
"typescript": "3.0.1" | ||
}, | ||
"jest": { | ||
"testRegex": "__tests__/.*\\.test\\.js$" | ||
}, | ||
"dependencies": { | ||
"@types/graphql": "0.13.4", | ||
"debug": ">=2 <3" | ||
@@ -43,0 +50,0 @@ }, |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
264
34239
3
11
+ Added@types/graphql@0.13.4
+ Added@types/graphql@0.13.4(transitive)