Hello there @Sometom and welcome to the community!
I hope you like it here 💪
Can you please send over the full script you are using?
Looking forward to hearing from you!
Cheers,
Matias
This works:
const functions = require('@google-cloud/functions-framework');
const monday = require('monday-sdk-js');
functions.http('helloHttp', (req, res) => {
const mondayClient = monday();
mondayClient.setApiVersion("2023-10");
mondayClient.setToken("?????");
try {
const id = req.body.payload.inputFields.itemId;
const query = `query {
items(ids: ` + id + ` ) {
column_values(ids: ["text1", "email1", "text8", "email4"]) {
id
text
}
}
}`;
const response = mondayClient.api(query);
response.then(r => console.log(r.data));
res.status(200).send(req.body);
} catch (err) {
console.error(err);
}
});
This doesn’t:
const functions = require('@google-cloud/functions-framework');
const monday = require('monday-sdk-js');
functions.http('helloHttp', (req, res) => {
const mondayClient = monday();
mondayClient.setApiVersion("2023-10");
mondayClient.setToken("?????");
try {
const id = req.body.payload.inputFields.itemId;
const query = `query ($itemId: :ID!]) {
items(ids: $itemId ) {
column_values(ids: :"text1", "email1", "text8", "email4"]) {
id
text
}
}
}`;
const response = mondayClient.api(query, { "itemId" : id });
response.then(r => console.log(r.data));
res.status(200).send(req.body);
} catch (err) {
console.error(err);
}
});
(obviously left out the tokens 🙂 )
Hello again,
I am not sure I understand the issue.
The first script looks good and it is working for you. Why is that not an option?
Why are you trying to pass the id as mondayClient.api(query, { "itemId" : id })
?
The issue is that both of the examples work in the App Playground. I’d expect both of them to work in scripts as well.
I prefer the second example because the first one is subject to injection attacks that can completely change the meaning of the query. I suspect many other developers would agree the second structure is vastly preferred. We’re dealing with PII, so I want to make sure we’re respecting the sensitivity of the data we have…
I need to implement updates as well, so I’d like to figure out how to do variable substitution to lower the risk of corruption.
Pretty easy -
- you should pass the variables object to the api method as the variables key of the options object (options is the second argument
.api(query: string, options: { variables: object, ...moreOptions})
).
const response = mondayClient.api(query, { variables: { itemId : id} });
would work.
I 100% agree with you that string manipulation is a terrible for graphql unless its concatenating query fragments (that are fixed strings).
That said, you are not validating Id in any way before using it! I like zod
plus validator
for this - something like the following.
const z = require('zod');
const validator = require('validator');
// define your validation schema outside the function
const inputFieldsSchema = z.object({
itemId: z.coerce.string().refine(validator.isInt),
});
// i've moved this to the file scope, instead of function scope, this way you don't have to
// allocate the query on every request.
const query = `query ($itemId: [ID!]) {
items(ids: $itemId ) {
column_values(ids: ["text1", "email1", "text8", "email4"]) {
id
text
}
}
}`;
functions.http('helloHttp', (req, res) => {
//setup code
try {
const { itemId: id } = inputFieldsSchema.parse(req.body.payload.inputFields);
//rest of your code
} catch (err) {
console.error(err)
}
});
Beautiful, thanks @anon29275264.
Yes, the example was a bit reckless and reduced to fit, but I also appreciate the pointers to other libraries; I’m still learning what javascript libraries are available…
Glad that was just for the example/test you were doing!
Zod is pretty decent for what we do with monday. If you were doing something with defined JSON schemas there are other tools which may work better. But for inputFields there isn’t anything generic since the developer defines it, and we also often need to manipulate things at the same time - such as coercing to string.