Skip to content

Instantly share code, notes, and snippets.

@StrongerMyself
Last active July 5, 2019 07:08
Show Gist options
  • Save StrongerMyself/deeb54428c2eea3524523ed840dec2dc to your computer and use it in GitHub Desktop.
Save StrongerMyself/deeb54428c2eea3524523ed840dec2dc to your computer and use it in GitHub Desktop.
Graphql parser AST query for optimal ORM query. Get relation map by spec relation list.
import { GraphQLResolveInfo } from 'graphql'
const unique = (arr = []) => {
let obj = {}
for (let i = 0;i < arr.length;i++) {
let str = arr[i]
if (!!str) obj[str] = true
}
return Object.keys(obj)
}
export const schemaRelBySpec = (info: GraphQLResolveInfo, spec = []) => {
let rel = []
info.fieldNodes.forEach(node => {
rel.push(...nodeMap(node, info.fragments, spec))
})
return unique(rel)
}
const nodeMap = (node, fragments, spec) => {
const { selectionSet } = node
const fields = fieldMap(selectionSet as [], fragments)
return spec.filter(name => fields.indexOf(name) >= 0)
}
const fieldMap = (selectionSet, fragments, parent = '') => {
let field = []
let value = parent
let { selections } = selectionSet
selections.forEach(el => {
let { kind, name, selectionSet } = el
if (kind === 'FragmentSpread') {
let { selectionSet } = fragments[name.value]
let subField = fieldMap(selectionSet, fragments, value)
field.push(...subField)
} else {
if (name) {
value = name.value
if (parent) value = `${parent}.${value}`
field.push(value)
}
if (selectionSet) {
let subField = fieldMap(selectionSet, fragments, value)
field.push(...subField)
}
}
})
return [...field]
}
import { IResolvers } from 'graphql-tools'
import { getCustomRepository } from 'typeorm'
import { schemaRelBySpec, schemaWhereByArgs } from '../../../utils'
import { OrderRepository } from '../'
const rp = () => getCustomRepository(OrderRepository)
const relationSpec = ['items', 'address']
const resolvers: IResolvers = {
Query: {
Orders: async (_, args, context, info) => {
const relations = schemaRelBySpec(info, relationSpec)
const where = schemaWhereByArgs(args)
return await rp().find({where, relations})
},
Order: async (_, { id }, context, info) => {
const relations = schemaRelBySpec(info, relationSpec)
return await rp().findOne(id, {relations})
},
},
}
export default resolvers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment