Skip to content

Instantly share code, notes, and snippets.

@Azerothian
Last active May 1, 2022 04:27
Show Gist options
  • Save Azerothian/dc84f009a94579b5bb43 to your computer and use it in GitHub Desktop.
Save Azerothian/dc84f009a94579b5bb43 to your computer and use it in GitHub Desktop.
Convert JS Objects to GraphQL Queries
// Babel 2015 - ES6
// Convert a complex JS Object to GraphQL Query, should handle most use cases as of 21/01/2016
const o = {
query: {
fields: {
complex: {
aliasFor: "Products",
processArgs: {
coupon: (value) => {
return `"${JSON.stringify(value).replace(/"/g, "\\\"")}"`; // passing json string as a argument
}
},
args: {
coupon: {
name: {
$eq: "Test",
}
},
complexCoupon: {
name: {
$eq: "Test",
}
}
},
fields: {
"...productFields": null
},
},
products: {
aliasFor: "Products",
args: {
coupon: "coupon",
buildingCode: "code"
},
fields: {
"...productFields": null
}
}
}
},
productFields: {
fragment: "Product",
fields: {
id: null,
"... @include": { // 5.4.1.2 Fragment Spread Type Existence
args: {
if: true
},
fields: {
name: null
},
},
"... on User": { // 5.4.1.2 Fragment Spread Type Existence
fields: {
name: null
},
},
name: null,
description: null,
options: {
fields: {
plan: {
fields: {
renew: null
},
},
},
},
}
}
}
export default function createGQLQuery(obj) {
let result = Object.keys(obj).map((k) => {
let query = `${k}`;
let element = obj[k];
if (element) {
if (element.aliasFor) {
query = `${k}:${element.aliasFor}`;
}
if (element.fragment) {
query = `fragment ${k} on ${element.fragment}`;
}
if (element.args) {
let args = Object.keys(element.args).map((argKey) => {
let argVar = "", processed = false;
if (element.processArgs) {
if (element.processArgs[argKey]) {
argVar = element.processArgs[argKey](element.args[argKey]);
processed = true;
}
}
if (!processed) {
if (typeof element.args[argKey] === "object") {
argVar = JSON.stringify(element.args[argKey]).replace(/\"([^(\")"]+)\":/g, "$1:");
} else {
argVar = `"${element.args[argKey]}"`;
}
}
return `${argKey}:${argVar}`;
}).join();
query = `${query}(${args})`;
}
if (element.fields) {
let fields = createGQLQuery(element.fields);
query = `${query}${fields}`;
}
}
return `${query}`;
}).join();
return `{${result}}`;
}
const query = createGQLQuery(o);
console.log(query);
document.body.innerHTML = query;
@Noitidart
Copy link

Noitidart commented Feb 16, 2017

This doesn't work for nested object. This worked for me:

function isObject(avar) {
    // cosntructor.name tested for `function Animal(){}; var a = new Animal(); isObject(a);` will return true otherwise as it is [Object object]
    return Object.prototype.toString.call(avar) === '[object Object]' && avar.constructor.name === 'Object';
}
function createGqlQuery(obj) {
    let shape = [];
  
    for (let [key, val] of Object.entries(obj))
      shape.push(isObject(val) ? `${key} { ${createGqlQuery(val)} }` : key);

    return shape.join(' ');
}

const SHAPE = {
    id: 'string.isRequired',
    name: 'string.isRequired',
    address: 'string.isRequired',
    creator: {
        displayname: 'string.isRequired',
        id: 'string.isRequired'
    },
    owner: {
        displayname: 'string.isRequired',
        id: 'string.isRequired'
    },
    level0: {
        level1: {
            level2: {
                levelLast: 'bool'
            }
        }
    }
}

console.log(createGqlQuery(SHAPE)); // outputs "id name address creator { displayname id } owner { displayname id } level0 { level1 { level2 { levelLast } } }"

@tamlyn
Copy link

tamlyn commented May 1, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment