Open daniablank opened 2 years ago
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.
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;
}
},
}
};
As you can see, it uses the data in one collection, "variables", to update another collection, "models".
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 https://github.com/VulcanJS/vulcan-npm/issues/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.
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.