Tom
Tom

Reputation: 4846

How to use object as keys in an elegant hash-style way

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 ?

Upvotes: 2

Views: 169

Answers (4)

Steve
Steve

Reputation: 10886

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 }
];

Upvotes: 1

Masood
Masood

Reputation: 21

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));


Upvotes: 2

Helios Live
Helios Live

Reputation: 153

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.

Upvotes: -1

Bergi
Bergi

Reputation: 665378

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]]
));

Upvotes: 0

Related Questions