Express validator- validate array of objects as request body - wildcard

I am trying to validate array of objects using wildcards. The req.body will be just an array of objects.
[{id:1},
{id:2}
]
If it was of this format
{
array: [{id:1}]
}
wild card would be array.*.id;
What am I doing wrong here.
I looked into github issue in express-validator repo and was trying follow this https://github.com/express-validator/express-validator/issues/67#issuecomment-410874697
const app = require("express")();
const {
validationResult,
body
} = require('express-validator');
app.post("/post",
[body().not().isArray().withMessage("success"),
body("*.id").not().isEmpty().withMessage("yeaaaa")],
(req,res,next)=>{
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
res.send("Passed validation")
})
app.listen(3000,()=>console.log("running on express !!!"))

Related

Unable to use array's method "find" in Vue 3

I am trying to get current location of a user and then push it into array. Before I do so, I check whether a city with the same name is already there. In that case, I won't push it into the array. However, when I am trying to check it, it says: Uncaught (in promise) TypeError: Cannot read properties of null (reading 'find').
const found = ref(false);
const weatherResponse = ref([]);
function getLocation() {
console.log("SETTING LOCATION");
navigator.geolocation.getCurrentPosition((position) => {
console.log(`Lat: ${position.coords.latitude}, Lon: ${position.coords.longitude}`);
if (position.coords.latitude && position.coords.longitude) {
axios.get(`https://api.weatherapi.com/v1/current.json?key=${API_KEY}&q=${Math.round(position.coords.latitude)},${Math.round(position.coords.longitude)}&aqi=no`)
.then((response) => {
found.value = weatherResponse.value.find((item) => item.location.name == response.data.location.name);
if (response.data?.error?.code != 1006 && !found.value) {
weatherResponse.value.push(response.data);
this.$store.commit("addToList", response.data);
console.log(weatherResponse.value);
}
})
}
},
(error) => {
console.log(error.message);
}
)
}
I've already tried using fetch, axios to grab the API, but the "find()" method is still not working. Regarding "found" variable, I tried using it in ref as well as declaring it as "let found".
After trying and testing, I've finally managed to get everything to work. My issue was in (weirdly) main.js. Because it was set out like this: createApp(App).use(cors, store).mount('#app') it, I guess, caused VueX.store not to load in properly because mounted hook was called and it was throwing all sorts of mistakes. Putting it like const app = createApp(App); app.use(store); app.use(cors); app.mount("#app"); actually made it work.

Using fetch data as array in Vue3

I'm using a composable provided by Vuejs.org that looks like this
// fetch.js
import { ref, isRef, unref, watchEffect } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
function doFetch() {
// reset state before fetching..
data.value = null
error.value = null
// unref() unwraps potential refs
fetch(unref(url))
.then((res) => res.json())
.then((json) => (data.value = json))
.catch((err) => (error.value = err))
}
if (isRef(url)) {
// setup reactive re-fetch if input URL is a ref
watchEffect(doFetch)
} else {
// otherwise, just fetch once
// and avoid the overhead of a watcher
doFetch()
}
return { data, error }
}
And within the script tag I'm using
let loopableValues = ref([])
const { data, error } = useFetch(
'https://jsonplaceholder.typicode.com/todos/',
)
loopableValues.value = data
return { loopableValues }
My issue is that the variable "data" is not a pure array that I can loop using something like this in the template:
<div v-for="value in loopableValues" :key="value.id"> {{ value.id}}</div>
Cause when I run this I get "Uncaught (in promise) TypeError: value is undefined". So I think I need to handle the promise somehow in order to loop out the data as above, but I'm stuck and don't know how to go forward. Do I need to use a function on the data coming back from the fetch composable or is it something else I'm misssing?

How to prevent the router.asPath useEffect from rendering twice on load while using NextJs and getServerSideProps? [duplicate]

This question already has answers here:
Why is my React component is rendering twice?
(8 answers)
Closed 8 months ago.
I am building an explore page with url query parameters (NextJs page with getServerSideProps)
If an external user goes onto this url domain.com/explore?type=actions&category=food it will fetch on the DB the data for "actions" and "food"
If an internal user uses on-page filters, it generates a new url domain.com/explore?type=actions&category=food&orderBy=points and I then fetch the data and render.
To do so, I am basically setting up a useEffect with the [router.asPath] dependency. The problem is that it renders twice on load for external users (due to gerServerSideProps ?) and therefore fetching the data twice :(
Any hints ? Thanks !
useEffect(() => {
// parsing the url
const url = location.search
const urlQuery = url.slice(1)
const result = {}
urlQuery.split("&").forEach(part => {
const item = part.split("=");
result[item[0]] = decodeURIComponent(item[1]);
});
console.log(result)
// Updating forms/filters states and setting up query parameters
queryParams = [] // reseting the params
setFiltersData(prevFiltersData => {
return {
...prevFiltersData,
thumbType: result.type,
}
})
if (result.field) {
setFiltersData(prevFiltersData => {
return {
...prevFiltersData,
categoryField: result.field,
categoryOperator: result.fieldOp,
categoryValue: result.fieldVal,
}
})
queryParams.push(where(result.field, result.fieldOp, decodeURIComponent(result.fieldVal)))
}
if (result.orderBy) {
setFiltersData(prevFiltersData => {
return {
...prevFiltersData,
orderFieldActions: result.orderBy,
orderOperatorActions: result.orderType,
}
})
queryParams.push(orderBy(result.orderBy, result.orderType))
}
setSearchParams(queryParams) // saving query params to state for subsequent data fetch
getFilteredData(result.type) // Fetching data from the DB
setInitialLoading(false)
}, [router.asPath])
Finally found a solution with this thread. https://github.com/vercel/next.js/issues/35822
The problem is due to React being used in "Strict mode" in the next.config.js.
https://reactjs.org/docs/strict-mode.html
Solution :
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,
experimental: {
scrollRestoration: true,
},
images: {
domains: ['lh3.googleusercontent.com', 'graph.facebook.com', 'firebasestorage.googleapis.com'],
},
}
module.exports = nextConfig
Switching the strictMode to false

Cloud vision api face detection no image present error

We are getting No image present. error while attempting face detection with the cloud vision api.
We are using code from the official documentation.
Please see the code below.
const request1={
"requests":[
{
"image":{
"content": imgdatauri //It contains image data uri
},
"features": [
{
"type":"FACE_DETECTION",
"maxResults":1
}
]
}
]
};
client
.annotateImage(request1)
.then(response => {
console.log(response);
response.send(response);
})
.catch(err => {
console.error(err);
response.send(err);
});
Here is the error message.
Error: No image present.
at _coerceRequest (/rbd/pnpm-volume/e40024d2-3d05-4f3d-a435-6d4e6ca96fb0/node_modules/.registry.npmjs.org/#google-cloud/vision/1.1.3/node_modules/#google-cloud/vision/src/helpers.js:69:21)
at ImageAnnotatorClient.<anonymous> (/rbd/pnpm-volume/e40024d2-3d05-4f3d-a435-6d4e6ca96fb0/node_modules/.registry.npmjs.org/#google-cloud/vision/1.1.3/node_modules/#google-cloud/vision/src/helpers.js:224:12)
at PromiseCtor (/rbd/pnpm-volume/e40024d2-3d05-4f3d-a435-6d4e6ca96fb0/node_modules/.registry.npmjs.org/#google-cloud/promisify/1.0.2/node_modules/#google-cloud/promisify/build/src/index.js:71:28)
at new Promise (<anonymous>)
at ImageAnnotatorClient.wrapper [as annotateImage] (/rbd/pnpm-volume/e40024d2-3d05-4f3d-a435-6d4e6ca96fb0/node_modules/.registry.npmjs.org/#google-cloud/promisify/1.0.2/node_modules/#google-cloud/promisify/build/src/index.js:56:16)
We would like to know what we need to do to resolve the issue.
Method 1:
In case of vision API, if image is stored locally you must convert that image to base64 string. Now this converted string is passed as value to content.
Make sure that you are converting image to base64 string and then passing to the content value.
There are some services available online to convert image to base64 string. You can also convert image to base64 by writing a piece of code. You can find services online and select anyone them. I am providing link to one service.
https://www.browserling.com/tools/image-to-base64
Method 2:
You can provide public url of image to vision API.
{
"requests":[
{
"image":{
"source":{
"imageUri": PUBLIC_URL
}
},
"features":[
{
"type":TYPE_OF_DETECTION,
"maxResults":MAX_NUMBER_OF_RESULTS
}
]
}
]
}
Method 3:
You can create bucket and put image there.
Now you can provide this image object URL or path.
I think this will help you.
Thank you.
I have created a Cloud Function with Cloud Storage Trigger, my function gets triggered ( with event ) when I upload an image file I can see there is event.mediaLink event.selfLink, I tried using both to load image, but it keeps complaining about No Image being present
here is the code
exports.analyzeImage = function(event) {
const vision = require('#google-cloud/vision');
const client = new vision.ImageAnnotatorClient();
console.log('Event', event.mediaLink)
let image = {
source: {imageUri: event.mediaLink}
};
return client.labelDetection(image).then(resp => {
let labels = resp[0].labelAnnotations.map( l => {
return {
description: l.description,
score: l.score
};
});
return labels;
// const dataset = bigquery.dataset('dataset')
// return dataset.table
}).catch(err => {
console.error(err)
})
}

how to pass format to google cloud translation API using the client library?

We are using google cloud translation API in our express application.
I am trying to do translations using the client library instead of making an API request every time.
1. What I want to know is how to pass the options like format (text or html) to the api while using the client library?
I can achieve this via making http requests using requestjs like this:
var request = require('request');
var url = 'https://translation.googleapis.com/language/translate/v2';
var options1 = {
q: 'amore mio',
target: 'hi',
format: 'text',
source: 'it',
key: 'my API key'
}
request.post({url:url, qs:options1}, (err, res, body)=> {
if(err) {
console.log('ERR: ', err);
}
console.log('RES: ', res.statusCode);
console.log('Body: ', body);
})
But the sample for using client library shows only this:
const {Translate} = require('#google-cloud/translate');
// Your Google Cloud Platform project ID
const projectId = 'YOUR_PROJECT_ID';
// Instantiates a client
const translate = new Translate({
projectId: projectId,
});
// The text to translate
const text = 'Hello, world!';
// The target language
const target = 'ru';
// Translates some text into Russian
translate
.translate(text, target)
.then(results => {
const translation = results[0];
console.log(`Text: ${text}`);
console.log(`Translation: ${translation}`);
})
.catch(err => {
console.error('ERROR:', err);
});
Is there a way I can pass options like 'format' using the client library?
How can I pass an array of strings to the q attribute (querystring) of the options object in the first method? If I pass an array directly like:
q: ['amore mio', 'grazie']
I get an error message :
RES: 400
Body: {
"error": {
"code": 400,
"message": "Required Text",
"errors": [
{
"message": "Required Text",
"domain": "global",
"reason": "required"
}
]
}
}
With respect to question 2 about passing the array of input arguments, this works fine if you use cURL to send the POST request similar to this example. I have tried it myself with success. I have tried to do different manipulations with your code from snipper 1 with the request library, but it seems as if the request library is not passing the array correctly. I would generally suggest using the client library which can successfully handle arrays in the input text.
Okay after a little research I just tried to pass options object with format and other properties (like source and target language) instead of target, and it worked.
So this can be achieved by:
const options = {
to: target,
format: 'html',
prettyPrint: true
}
translate
.translate(text, options)
.then(results => {
const translation = results[0];
console.log('flag: ', Array.isArray(translation));
console.log(`Text: ${text}`);
console.log(`Translation: ${translation}`);
})
.catch(err => {
console.error('ERROR:', err);
});
Use JSON.stringify
`https://translation.googleapis.com/language/translate/v2?q=${JSON.stringify([array]}`

Resources