0

I'm trying to merge 2 dot notation strings into a GrahQL query with only javascript (it can be ES6/typescript).

For example, let say that I have an array of strings

[
    'firstName', 
    'lastName', 
    'billing.address.street', 
    'billing.address.zip', 
    'shipping.address.street', 
    'shipping.address.zip'
]

The expected query string output would be (white spaces are not important)

firstName, lastName, shipping{address{street, zip}}, billing{address{street, zip }}

I can convert 1 by 1 the dot notation to a query string, but how do I merge all of that together? I got a function that take street.name and output street { name }. So this function would do it

convertToString(inputString) {
    let result = '';

    if (inputString.indexOf('.') === -1) {
      result = inputString;
    } else {
      const inputArray = inputString.split('.');
      for (let i = inputArray.length - 1; i >= 0; i--) {
        if (i === 0) {
          result = inputArray[i] + result;
        } else {
          result = '{' + inputArray[i] + result + '}';
        }
      }
    }
    return result;
}

console.log(convertToString('address.street')); // address { street }

But then how would I loop through all strings and get only 1 GraphQL query string that combines the same properties into a group. The main issue is how do I merge the 2 dot notation strings without losing anything and without having duplicates (at this point, I can get this address { name } address { zip } but when this runs on the GraphQL server, only the latter is kept and so only the zip shows up in the result.

I tried creating temporary object that represent the structure, but that didn't work out so good.

1 Answer 1

3

Revised Answer

Based on your revised question and requirements, here's a revised answer. This will recursively build an object from nested dot notations, and then leverage JSON.stringify to build the query string (with some string manipulations);

function buildQuery(...args) {
  const set = (o = {}, a) => {
    const k = a.shift();
    o[k] = a.length ? set(o[k], a) : null;
    return o;
  }
  
  const o = args.reduce((o, a) => set(o, a.split('.')), {});
  
  return JSON.stringify(o)
    .replace(/\"|\:|null/g, '')
    .replace(/^\{/, '')
    .replace(/\}$/, '');
}

const query = buildQuery(
  'firstName', 
  'lastName', 
  'billing.address.street', 
  'billing.address.zip', 
  'shipping.address.street', 
  'shipping.address.zip'
);

console.log(query);

Original Answer

I would suggest converting the individual dot notation strings into an object first, and then converting the object to a string.

function buildQuery(...args) {
    let q = {};

    args.forEach((arg) => {
        const [ o, a ] = arg.split('.');
        q[o] = q[o] || [];
        if (a) q[o] = q[o].concat(a);
    });

    return Object.keys(q).map((k) => {
        return q[k].length ? `${k} \{ ${q[k].join(', ')} \}` : k;
    }).join(', ');
}

const query = buildQuery('person.name', 'person.email', 'street.name', 'street.zip');
console.log(query);
// "person { name, email }, street { name, zip }"
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks this looks really close the solution that I'm looking for, however after updating my question (I just did so you probably didn't see it). If I run the buildQuery with the list of arguments provided in the question, the answer has some extra curly braces on the regular string lastName { }, billing { address, address }, you can see lastName should not have { }
I've updated my answer. It may be possible to improve the code a little, but it seems to work.
Thanks a lot, just 1 little thing, when I try on jsbin, it throws an error on the args.forEach, it goes away after adding spread operator to args (...args). Would you mind updating your answer.
Ah yes, sorry. I removed the spread when I saw you were passing an array of arguments instead, and didn't update the function call. I see your strings actually go three levels deep. This only works with two levels at the moment, so will need to be made recursive.
Oh I just saw your comment about the 2 levels deep, how hard would it be to make it recursive?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.