Skip to content

Instantly share code, notes, and snippets.

@dimensi
Last active November 29, 2018 09:00
Show Gist options
  • Select an option

  • Save dimensi/21e42a1352cbcee643c6f6fda74eab12 to your computer and use it in GitHub Desktop.

Select an option

Save dimensi/21e42a1352cbcee643c6f6fda74eab12 to your computer and use it in GitHub Desktop.
Graphql property collector
{
"kind": "Document",
"definitions": [
{
"kind": "OperationDefinition",
"operation": "query",
"variableDefinitions": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "users",
"loc": {
"start": 131,
"end": 136
}
},
"arguments": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "socials",
"loc": {
"start": 143,
"end": 150
}
},
"arguments": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "fb",
"loc": {
"start": 153,
"end": 155
}
},
"arguments": [],
"directives": [],
"loc": {
"start": 153,
"end": 155
}
}
],
"loc": {
"start": 151,
"end": 157
}
},
"loc": {
"start": 143,
"end": 157
}
},
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "privateData",
"loc": {
"start": 163,
"end": 174
}
},
"arguments": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "education",
"loc": {
"start": 183,
"end": 192
}
},
"arguments": [],
"directives": [],
"loc": {
"start": 183,
"end": 192
}
},
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "birthday",
"loc": {
"start": 201,
"end": 209
}
},
"arguments": [],
"directives": [],
"loc": {
"start": 201,
"end": 209
}
},
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "car",
"loc": {
"start": 218,
"end": 221
}
},
"arguments": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "model",
"loc": {
"start": 233,
"end": 238
}
},
"arguments": [],
"directives": [],
"loc": {
"start": 233,
"end": 238
}
},
{
"kind": "Field",
"name": {
"kind": "Name",
"value": "registrationMark",
"loc": {
"start": 249,
"end": 265
}
},
"arguments": [],
"directives": [],
"loc": {
"start": 249,
"end": 265
}
}
],
"loc": {
"start": 222,
"end": 275
}
},
"loc": {
"start": 218,
"end": 275
}
}
],
"loc": {
"start": 175,
"end": 285
}
},
"loc": {
"start": 163,
"end": 285
}
}
],
"loc": {
"start": 137,
"end": 291
}
},
"loc": {
"start": 131,
"end": 291
}
}
],
"loc": {
"start": 128,
"end": 293
}
},
"loc": {
"start": 128,
"end": 293
}
}
],
"loc": {
"start": 0,
"end": 293
}
}
const flattenObject = (obj, prefix = '', arr = []) =>
Object.keys(obj).reduce((acc, k) => {
acc.push({
propertyName: k,
propertyPath: prefix.length ? `${prefix}.${k}` : k
})
if (Object.keys(obj[k]).length) {
const childAcc = flattenObject(obj[k], k, [])
acc.push(...childAcc)
}
return acc;
}, arr);
// graphql-fields
console.log(flattenObject({
"profile": {
"firstName": {},
"lastName": {},
"middleName": {}
},
"email": {},
"id": {}
}))
/**
[ { propertyName: 'profile', propertyPath: 'profile' },
{ propertyName: 'firstName', propertyPath: 'profile.firstName' },
{ propertyName: 'lastName', propertyPath: 'profile.lastName' },
{ propertyName: 'middleName',
propertyPath: 'profile.middleName' },
{ propertyName: 'email', propertyPath: 'email' },
{ propertyName: 'id', propertyPath: 'id' } ]
*/
const ast = require('./ast.json')
const astWalker = (fields, cb, acc) => {
const iter = (field, parent, acc) => {
const newAcc = cb(field, parent, acc);
const { selectionSet } = field
if (!selectionSet) return
selectionSet.selections.forEach(child => iter(child, field, newAcc))
}
iter(fields, null, acc)
return acc;
}
const collectParent = (propertyName, parentName, tree) => {
if (!parentName) return propertyName;
let name = `${parentName}.${propertyName}`
let currentParent = parentName
while (currentParent) {
const parentField = tree.find(field => field.propertyName === currentParent)
if (!parentField.parent) {
break;
}
name = `${parentField.parent}.${name}`
currentParent = parentField.parent
}
return name;
}
const collectProperties = (tree) => tree.map(({ propertyName, parent}) => ({
propertyName,
propertyPath: collectParent(propertyName, parent, tree)
}))
const tree = astWalker(ast.definitions[0], (field, parent, acc) => {
if (field.name) {
acc.push({
propertyName: field.name.value,
parent: parent.name ? parent.name.value : null
})
}
return acc;
}, [])
console.log(collectProperties(tree))
/**
[ { propertyName: 'users', propertyPath: 'users' },
{ propertyName: 'socials', propertyPath: 'users.socials' },
{ propertyName: 'fb', propertyPath: 'users.socials.fb' },
{ propertyName: 'privateData',
propertyPath: 'users.privateData' },
{ propertyName: 'education',
propertyPath: 'users.privateData.education' },
{ propertyName: 'birthday',
propertyPath: 'users.privateData.birthday' },
{ propertyName: 'car', propertyPath: 'users.privateData.car' },
{ propertyName: 'model',
propertyPath: 'users.privateData.car.model' },
{ propertyName: 'registrationMark',
propertyPath: 'users.privateData.car.registrationMark' } ]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment