Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to write API schemas in Vulcan Next? #139

Open
daniablank opened this issue Dec 11, 2021 · 4 comments
Open

Is there a way to write API schemas in Vulcan Next? #139

daniablank opened this issue Dec 11, 2021 · 4 comments
Assignees

Comments

@daniablank
Copy link

In particular: I'm trying to make an API function that takes in a string with variable names in it, e.g. "one + two", which should then be substituted in by the values of variables in those names in the variables collection (which should already have entries with name "one" and value 1, etc), and add to a different collection the evaluated result. I've written this and other functions in regular GraphQL, and would like to transfer them to Vulcan instead. Is this doable? For Vulcan Meteor, I looked at the page https://docs.vulcanjs.org/api-schemas.html , but apparently that's not how it works anymore. I asked in Slack, and it was suggested that I make an issue here.

@eric-burel eric-burel self-assigned this Dec 11, 2021
@eric-burel
Copy link
Collaborator

eric-burel commented Dec 11, 2021

Yep thank you for opening a ticket, it will be easier to track. Are you able to share code samples here so I can see how it could be structured?

Also, do you think your API endpoint is tied to a specific model? Like your "Variable" collection? Or is it a totally independant endpoint?

Because we could add typeDefs and resolvers fields to graphql server models to make this more intuitive, and automatically load them into the graphql API.

@daniablank
Copy link
Author

daniablank commented Dec 11, 2021

Here's the original resolver, edited for brevity:

calculateResult: async(obj, args, context, info) => {


     const db = mongoose.connection;

     const getVariable = async function(name) {
       return await db.collection("variables").find({/* some filters*/, name: name}).toArray()[0];
     }

     let allRelevantVariables = await db.collection("variables").find({/* some filters */}).toArray();

   
     const matchVariable = function(str) {
       for (let i = 0; i < allRelevantVariables.length; i++){
         const possibleVar = allRelevantVariables[i]["name"];
         if (str.includes(possibleVar)) {
           return allRelevantVariables[i];
         }
       }
       return false;
     }


     const inputString = args.expression;
     const  percolateVariables = async function(str) {
       let firstFoundVariable = matchVariable(str);
       if (! firstFoundVariable) {
         return str;
       } else {
         const fullFirstVarValue : String = String(await percolateVariables(firstFoundVariable["value"]));
         const truncatedFirstVarValue = replaceAll(fullFirstVarValue, "=", "");          
         const substitutedStr = replaceAll(str, firstFoundVariable["name"], truncatedFirstVarValue);
         return await percolateVariables(substitutedStr);
       }
     }
     let fullString = await percolateVariables(inputString);
       let assignedValue = /* Parse and evaluate fullString */;
       db.collection("models").findOneAndUpdate({/* some filters */}, {$set: {/* misc fields */, score: assignedValue}});
       return assignedValue;
     }
  },
 }
};

@daniablank
Copy link
Author

As you can see, it uses the data in one collection, "variables", to update another collection, "models".

@eric-burel
Copy link
Collaborator

eric-burel commented Dec 13, 2021

Hi,
I've worked a bit on this this afternoon:

  • I've added more comments on typings in vulcan NPM. I am not sure they correctly show up yet in VS Code but I hope they will in a future release

  • Check https://github.com/VulcanJS/vulcan-next/blob/devel/src/models/sampleModel.server.ts => it demoes a "resolveAs" field now.
    This is a document-level resolver, so maybe not suited for your use case.

  • It's perfectly fine to add new queries and mutation to a Vulcan Next app: your code is fine. Just add it in src/pages/api/graphql.ts.

  • TypeScript documentation lives here: https://vulcan-npm.vercel.app/ (it's autogenerated so not extremely human friendly, but can still help)

  • However, I agree that this still require more documentation, I'll work on it.

  • Also, it would be great to make checking permissions easier and document filtering. See Create queriers in addition to mutators + standardize mutators vulcan-npm#82: mutators and querier let you get/update data, but add Vulcan logic as well (running callbacks, filtering unallowed fields)

  • For testing, I should add a demo, using either "supertest" (against Apollo Server Express, that's closer to the real life setup especially when using ctx.req) or "executeOperation" (but it needs to spawn a raw ApolloServer, might be slower?)

  • The pattern I propose is not optimized for batching (you need dataSources and stuff like that)

You can check how we seed data, in order to understand "mutators". They are the building blocks of Vulcan default resolvers, but not yet well exposed and they lack a "Read" counterpart.

If you want to simplify this code, a first step would be to use the "Connector" from Vulcan. They add some sugar over Mongoose with generic operations. But you are not obligated to do so, I really think your code is fine.
Vulcan is there to make the generic operation easy, but the non-generic stuff should preferably be written using barebones Mongoose/Apollo, exactly like you did.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants