2

I have the following code:

const { query1 } = require('query1')
const { query2 } = require('query2')
const { query3 } = require('query3')

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: "Query",
    fields: {
      query1,
      query2,
      query3
    }
  })
});

const permissions = shield(
  {
    Query: {
      query1: user,
      query2: user,
      query3: admin
    }
  }
)

(much longer in the reality)

And I'm looking for a way to make it clearer, like:

const { query1 } = require('query1')
const { query2 } = require('query2')
const { query3 } = require('query3')

const declaration = {
     query1: user,
     query2: user,
     query3: admin
}

const schema = new GraphQLSchema({
 query: new GraphQLObjectType({
   name: "Query",
   fields: someMagic(declaration)
 })
});

const permissions = shield(
 {
   Query: declaration
 }
)

But here declaration keys are the strings "query1", "query2" and "query3". Not the objects.

With a WeakMap we could have something like:

const declaration = new WeakMap();

declaration.set(query1, user);
declaration.set(query2, user);
declaration.set(query3, admin);

But I find it much less elegant. Is there another way ?

Tom
  • 4,666
  • 2
  • 29
  • 48
  • Where and how is `user` and `admin` defined? – Dai Sep 02 '22 at 09:58
  • 1
    _"But here declaration keys are the strings "query1", "query2" and "query3". Not the objects."_ - what you're asking for is impossible: `object` keys are **always** `string` or `Symbol` values - you can't use `object` values as keys for properties in other objects. – Dai Sep 02 '22 at 09:59
  • Also, why a `WeakMap` instead of a normal `Map`? – Dai Sep 02 '22 at 09:59
  • @Dai `user` and `admin` are defined just before, they are functions checking access rights. `WeakMap` was just an example, to try to find an elegant declaration. – Tom Sep 02 '22 at 11:45

4 Answers4

2

Hope this might help:

/*
queries['query1'] = require('query1') 
queries['query2'] = require('query2') 
queries['query3'] = require('query3') 

*/

let queries = {
  query1: { a: { $eq: "I am Query 1" }, permission: "user" }, //user can be String or object or whatever !
  query2: { b: { $eq: "I am Query 2" }, permission: "user" },
  query3: { c: { $eq: "I am Query 3" }, permission: "admin" },
};

let declaration = {};
let queryNames = Object.keys(queries);
for (let i in queryNames) {
  let curQueryName = queryNames[i];
  declaration[curQueryName] = queries[curQueryName]["permission"];
  //delete queries[curQueryName]["permission"]
}
console.log(JSON.stringify(declaration, null, 2));


Masood
  • 21
  • 4
  • 1
    [Don't use `for…in` enumerations on arrays!](https://stackoverflow.com/q/500504/1048572) Write `for (const curQueryName of queryNames)` or `for (const curQueryName in queries)` – Bergi Sep 11 '22 at 14:24
1

Instead of an object, you could have an array of objects, something like this:

const { query1 } = require('query1')
const { query2 } = require('query2')
const { query3 } = require('query3')

var declarations = [
  { query1, permissions: user },
  { query2, permissions: user },
  { query3, permissions: admin }
];

Then to extract fields and permissions objects:

var fields = {};
var queryPermissions = {};
for (let declaration of declarations) {
  for (let key of Object.keys(declaration)) {
    if (key !== 'permissions') {
      fields[key] = declaration[key];
      queryPermissions[key] = declaration.permissions;
    }
  }
}

For example:

const query1 = { query: 'sample query 1' };
const query2 = { query: 'sample query 2' };
const query3 = { query: 'sample query 3' };
const user = 'user';
const admin = 'admin';

var declarations = [
  { query1, permissions: user },
  { query2, permissions: user },
  { query3, permissions: admin }
];

var fields = {};
var queryPermissions = {};
for (let declaration of declarations) {
  for (let key of Object.keys(declaration)) {
    if (key !== 'permissions') {
      fields[key] = declaration[key];
      queryPermissions[key] = declaration.permissions;
    }
  }
}

console.log(fields);
console.log(queryPermissions);

Side Note:

Another advantage of doing it this way is that you can group queries by permissions, for instance:

var declarations = [
  { query1, query2, permissions: user },
  { query3, permissions: admin }
];
Steve
  • 10,435
  • 15
  • 21
0

It's not possible to construct an object that uses a variable's name as the property name but something else than the variable's value as the value. You'll have to spell them out twice, once for the permissions once for the resolvers:

const queryPermissions: {
  'query1': user,
  'query2': user,
  'query3': admin,
};
const queryResolvers: {
  'query1': require('query1').query1,
  'query2': require('query2').query2,
  'query3': require('query3').query3,
};

The destructured variables from the imports don't really help with anything here. However, if your module structure is really like this, and you're still using Common.js modules, then you can actually derive the queryResolvers object from the property names of the queryPermissions object:

const queryResolvers = Object.fromEntries(Object.keys(queryPermissions).map(fieldName =>
  [fieldName, require(fieldName)[fieldName]]
));
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • "if your module structure is really like this". Sadly, no, some modules exports multiple queries. But the idea was interesting. – Tom Sep 04 '22 at 15:41
  • Still, then do `Object.assign({}, require('some queries'), require('other queries))`, and access the queries by name on that object. Bonus: this pattern even works with ES6 namespace imports. – Bergi Sep 04 '22 at 15:48
-1

This should do the trick:

((function(t,d){
    var fields = {}
    for (const key in d) {
      fields[key] = t[key]
    }
    return fields
})(this, declaration)

{a, b, c} Is just shorthand for {a: a, b: b, c: c}

However, Global constants do not become properties of the window object, unlike var variables, so you might need to fiddle a bit with it.

  • 1
    What do you expect `this` to refer to? – Bergi Sep 08 '22 at 20:49
  • Could you elaborate, maybe the full code ? – Tom Sep 10 '22 at 14:01
  • Depending on where the piece of code is ran, this can refer to different things. If you run in in a browser global context then this refers to the window object. Like I said, the code isn't perfect. It runs into the issue of consts not being added to the window object. – Idea to Code Sep 12 '22 at 15:12