NestJS TypeORMCrudService - javascript

I need to use one of the basic TypeORMCrudService methods, for example, createOne, I got the body as dto(I guess) but the second parameter is the CrudRequest. Should I redefine its methods or what?

if I understand what you mean:
if you use repositoryT it's so easy to do it:
your controller should be like this:
#Get(':id')
async findOne(#Param('id', ParseIdPipe) id: number) {
return await this.unitService.findOne(id);
}
your service should be like this:
async findOne(id: number, ...relations: string[]): Promise<Entity> {
const record = await this.repository.findOne(id, { relations });
this.checkNotFound(record);
return record;
}
you can use :
const record = await this.repository.findOne(id, { relations });
const record = await this.repository.create({dto});
const record = await this.repository.find();
const record = await this.repository.delete(id);
const record = await this.repository.update(id, {dto});

Related

How to handle this javascript asynchronous function

I have this function in javascript node
exports.getUserEmailByAccess = async (moduleType) => {
let emailList = []
const foundUsers = await Access.find({moduleType:moduleType})
console.log(foundUsers);
await foundUsers.forEach(access => {
User.findById(access.userId)
.then(foundUser => {
console.log(foundUser.workerEmail);
emailList.push(foundUser.workerEmail)
})
});
console.log(emailList);
return emailList
}
What I want is to push into emailList array by looping object array, the above approach results in an empty array,so I tried a different following way
exports.getUserEmailByAccess = async (moduleType) => {
let emailList = []
const foundUsers = await Access.find({moduleType:moduleType})
console.log(foundUsers);
await foundUsers.forEach(access => {
const foundUser = User.findById(access.userId)
console.log(foundUser.workerEmail);
emailList.push(foundUser.workerEmail)
});
console.log(emailList);
return emailList
}
By doing this , the array list is getting filled but with an [undefined]strong text value, I come from a humble python control structure background, Please can I know why I am not able to push data into array even after using async/await
If the User.findById() returns a promise, I'd recommend using Promise.all() instead of individually running all promises using forEach to fetch documents of all foundUsers:
exports.getUserEmailByAccess = async (moduleType) => {
const foundUsers = await Access.find({ moduleType: moduleType });
console.log(foundUsers);
const userDocs = await Promise.all(
foundUsers.map((user) => User.findById(user.userId))
);
const emailList = userDocs.map((user) => user.workerEmail);
// or alternatively
// const emailList = userDocs.map(({workerEmail}) => workerEmail);
console.log(emailList);
return emailList;
};
you can give try this
exports.getUserEmailByAccess = async (moduleType) => {
let emailList = []
const foundUsers = await Access.find({ moduleType: moduleType })
console.log(foundUsers);
await foundUsers.map(async access => {
let result = await User.findById(access.userId);
if (result) {
emailList.push(foundUser.workerEmail)
}
});
console.log(emailList);
return emailList
}
UPDATED
await Promise.all(
foundUsers.map(async access => {
let result = await User.findById(access.userId);
if (result) {
emailList.push(foundUser.workerEmail)
}
})
])
console.log(emailList);
return emailList
How are your Models related? I think you might do a populate here if the Access Model has the ObjectId of the User Model. Something like this:
const foundUsers = await Access.find({ moduleType: moduleType }).populate({
path: 'users', // the name of the field which contains the userId
select: '-__v' // fields to bring from database. Can add a (-) to NOT bring that field
})
The idea is that you specify all the fields that you need. Then when you receive the data, you can do something like:
foundUsers.users.email

Export a variable from a function in Javascript

All i want is take userId variable's value to use anything.
async function getMyData(){
const token = '';
spotifyApi.setAccessToken(token);
const data = await spotifyApi.getMe();
let userId = data.body.id;
return userId;
}
const userId = getMyData();
console.log(userId)
console.log(userId) saying me this: {Promise <pending<}
With any async functions, don't forget to use await before function execution
/// ./getMyData.js
export async function getMyData(){
// ...
return userId;
}
/// ./otherFile.js
import {getMyData} from './getMyData.js'
(async function () {
const userId = await getMyData();
console.log(userId)
})()
you are using async await features in your code.
Thus the return type of your getMyData would actually be a Promise object.
More about Promises here
Now, heres how you can use your function in another file without having to use the await keyword.
import { getMyData } from '%your file path%';
getMyData().then(function(userId) {
// use the value of userId here
console.log(userId);
}

How can I find a message in a link

I was recently creating a bot.
Right now I am trying to find out if someone could help me with my -verify (mc uuid) command. It would check a URL to see if their uuid is in the fetched object. So, if I did -verify (uuid) and it is found, it would give me a role.
Code:
const Discord = require('discord.js');
const fetch = require('cross-fetch');
module.exports = {
name: `verify`,
async execute(message, args) {
fetch("https://api.hypixel.net/guild?key=29083d9d-58cf-4a71-95be-d24f31c018b7&name=Metanoia")
.then(result => result.json())
.then(({ guild }) => {
const role = message.guild.roles.cache.get('808886143416270899');
const uuid = args[0];
if(uuid) {
//
}
})
}
}
You receive an object from the API URL. Its guild property has a members array. The array contains objects with uuids. If you want to find one with the provided uuid, you can use the .find() method that returns the value of the first element in the array that satisfies the provided testing function.
In your testing function you can test if the object's uuid is the same as the member provided uuid:
const foundElement = array.find((el) => el.uuid === uuid);
In your code it looks like this:
const fetch = require('cross-fetch');
module.exports = {
name: `verify`,
async execute(message, args) {
const role = message.guild.roles.cache.get('808886143416270899');
const uuid = args[0];
if (!uuid) {
return message.channel.send(`uuid is not provided`);
}
try {
const result = await fetch('https://api.hypixel.net/guild?key=29083d9d-58cf-4a71-95be-d24f31c018b7&name=Metanoia');
const { guild } = await result.json();
const member = guild.members.find((member) => member.uuid === uuid);
if (!member) {
return message.channel.send(`No member found with uuid ${uuid}`);
}
// you can do anything with the found member
message.channel.send('```' + JSON.stringify(member, null, 2) + '```');
} catch (error) {
console.log(error);
message.channel.send('Oops, there was an error');
}
}
}
If your execute method is already an async function, you can use async/await to fetch the results. I used that in my code above.

How do I use a document's field from one collection to retrieve another document field from a different collection?

Here is how my database is structured:
challenges table &
users table
Here is the error I'm getting: error image
I want to use the "created_by" field which is also a document id for the users table, where I want to retrieve both the display name and the photo URL.
I'm not all the way sure how promises work and I have a feeling that is why I'm struggling, but the code I have thus far is below:
Data Retrieval:
UsersDao.getUserData(ChallengesDao.getChallenges().then(result => {return result['author'][0]})).then(result => {console.log(result)})
Challenges DAO:
export default class ChallengesDao {
static async getChallenges() {
const db = require('firebase').firestore();
// const challenges = db.collection('challenges').limit(number_of_challenges)
// challenges.get().then(())
const snapshot = await db.collection('challenges').get()
const names = snapshot.docs.map(doc => doc.data().name)
const createdBy = snapshot.docs.map(doc => doc.data().created_by)
const highScores = snapshot.docs.map(doc => doc.data().high_score.score)
return {challengeName: names, author: createdBy, score: highScores}
}
Users DAO:
const db = require('firebase').firestore();
export default class UsersDao {
static async getUserData(uid: string) {
let userData = {};
try {
const doc = await db
.collection('users')
.doc(uid)
.get();
if (doc.exists) {
userData = doc.data();
} else {
console.log('User document not found!');
}
} catch (err) {}
return userData;
}
}
You're getting close. All that's left to do is to call getUserData for each UID you get back from getChallenges.
Combining these two would look something like this:
let challenges = await getChallenges();
let users = await Promise.all(challenges.author.map((uid) => getUserData(uid));
console.log(challenges.challengeName, users);
The new thing here is Promise.all(), which combines a number of asynchronous calls and returns a promise that completes when all of them complete.
Your code looks a bit odd to me at first, because of the way you return the data from getChallenges. Instead of returning three arrays with simple values, I'd recommend returning a single array where each object has three values:
static async getChallenges() {
const db = require('firebase').firestore();
const snapshot = await db.collection('challenges').get();
const challenges = snapshot.docs.map(doc => { name: doc.data().name, author: doc.data().created_by, score: doc.data().high_score.score });
return challenges;
}
If you then want to add the user name to each object in this array, in addition to the UID that's already there, you could do:
let challenges = await getChallenges();
await Promise.all(challenges.forEach(async(challenge) => {
challenge.user = await getUserData(challenge.author);
});
console.log(challenges);

async Array.map() inside another map call

I have a method that receives a profiles array and I have to map for each profile and inside this map I have to map again in the photos propriety, which contains the pictures ids for requesting to an API for getting this picture.
The question is, where can I safely access this profiles array with their loaded photos for each respective profile?
profiles.map((profile, i) => {
let photos = []
Promise.all(profile.photos.map(async idPhoto => {
const res = await fetch(...)
const img = await res.blob()
photos.push(img)
}))
.then(() => profiles[i].photos = [...photos])
})
With the outer map function the way it currently is, the Promise.all() calls are discarded, so there is no way for your code to detect when they are complete.
However, since you also do not appear to be using the return value of the outer map, we can make it return an array of Promises that resolve when the inner their array of Promises is all resolved. And then we can use the same Promise.all(array.map()) pattern as we use for the inner map.
const photoRequests = profiles.map(async (profile, i) => {
let photos = []
await Promise.all(profile.photos.map(async idPhoto => {
const res = await fetch(...)
const img = await res.blob()
photos.push(img)
}));
profiles[i].photos = [...photos];
})
// And now...
await Promise.all(photoRequests);
// After this it is safe to access.
// Or, if the outer map is not in an async method:
Promise.all(photoRequests).then(() => {
// It is safe to access profiles here
});
I've refactored the outer map to be an async function (aids readability IMO), but you can put it back if you prefer. Just have the outer map function return the result of the Promise.all call.
As to what else could be improved here, the having variables photos and profile.photos is a little confusing, so consider renaming photos. Also make it const while you're at it, as it's never reassigned.
Unless there's some other code that manipulates the photos array, the array spread syntax is not needed. Same for the index variable. Final code might look something like:
const photoRequests = profiles.map(async profile => {
const loadedPhotos = []
await Promise.all(profile.photos.map(async idPhoto => {
const res = await fetch(...)
const img = await res.blob()
loadedPhotos.push(img)
}));
profile.photos = loadedPhotos;
})
await Promise.all(photoRequests);
Or you could use the fact that Promise.all resolves to an array containing the resolve values of the individual promises it received:
const photoRequests = profiles.map(async profile => {
profile.photos = await Promise.all(
profile.photos.map(async idPhoto => {
const res = await fetch(...)
return res.blob()
})
);
})
await Promise.all(photoRequests);
I think it would be better to separate each mapping into its own function, it makes it easier to read. I refactored your code into this:
let fetchPhoto = async (photoId) => {
// const res = await fetch(...);
// return res.blob();
return { imageData: photoId } // mock blob result
};
let mapPhotoIdToImage = async (profile) => {
let photos = profile.photos.map(fetchPhoto)
photos = await Promise.all(photos);
profile.photos = photos;
return profile;
};
let profileList = [{photos: ['id1', 'id2']}];
let result = await profileList.map(mapPhotoIdToImage);
result:
[{ photos: [ { imageData: 'id1' }, { imageData: 'id2' } ] }]

Categories