Post Request don't add the object in database (nestJs/phpmyadmin) - database

i'm trying to make a signup methode in nestJs. But the matter is that when i use my POST request to create a new user, my database don't add this new user in her list of users.
I created this method:
createUser(data: AuthDto){
const user = {
pseudo: data.username,
password: data.password,
pointEffort: 10,
roleId: 2,
id: 5
};
console.log(user);
const result = this.usersRepository.create(user);
return result;
}
The communication with the database works cause i can get the user i already created in phpmyadmin when i insert them with an SQL request.
Here are the entity in my nestJs:
import { Place } from "src/place/place.entity";
import { Science } from "src/science/science.entity";
import { TechnologieUser } from "src/technologie/technologieUser.entity";
import { Column, Entity, ManyToMany, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { Role } from "./role.entity";
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: Number;
#Column()
pseudo: String;
#Column()
password: String;
#Column()
pointEffort: Number;
#ManyToOne(type => Role, role => role.users)
role: Role;
#ManyToMany(type => Science, science => science.users)
scienceTab: Science[];
#OneToMany(type => TechnologieUser, technologieUser => technologieUser.user)
technologieTab: TechnologieUser[];
#OneToMany(type => Place, place => place.user)
inventaire: Place[];
}
And here the user table:
enter image description here
So when i click on a button to create a user, my request get sent and return the new user in the console.log but i never see this new user in my database. Thx for your help

From docs:
create - Creates a new instance of User. Optionally accepts an object literal with user properties which will be written into newly created user object
const user = repository.create() // same as const user = new User();
If you want to save the object try this:
const result = this.userRepository.save(this.usersRepository.create(user));

Related

TypeORM sets relation to null when reloading NestJS application

When I reload my NestJS application the foreign key gets set to null.
User table:
#Entity()
export class User {
#PrimaryGeneratedColumn()
#OneToMany(() => Marker, (marker) => marker.user)
#OneToMany(() => Vote, (vote) => vote.user)
id: number;
#Column
name: string
}
Vote table:
#Entity()
export class Vote {
#PrimaryGeneratedColumn()
id: number
#ManyToOne(() => User, (user) => user.id)
user: User;
}
When I try the application everything works and in the vote table the user gets set and everything works. But when I restart the application the foreign key user from the table vote gets set to null. There are no error messages or warnings so I'm confused to what is going on.
Delete the dist folder and re-run the server again.

How to make multple function calls to each element in observable stream return observable stream of "new" objects

I have an expression that takes an observable stream of posts and for each post evaluates a "posterName" and merges back in to the original post.
Before returning the post, is there a way to call another function to evaluate a second attribute (whether the post has been liked by current user) and then merge that back in with the posterName and original post.
Please see code and comment below
this.fService.postList$.pipe(
switchMap(_posts => { // switchMap to subscribe to inner
const getUsers$ = _posts
.map(post => // array map comments into posterName fetch
this.fService.getUserName(post.uid).pipe(
// once you have the username, rx map back into the comment with the username assigned
map(userName => ({...post, posterName: userName.first_name + " " + userName.last_name})),
catchError((err) => {
// Handle specific error for this call
console.log(err)
return of({...post, posterName: "Anonymous"})
}),
first()
)
//Where can I write a second function that takes the same posts ID
//and return a promise that I can "then" so I merge the resolved
//value in to the post i.e ({...post,posterName: somename , thirdThing: somevalue})
)
return forkJoin(...getUsers$); // forkJoin them all together for parallel execution
})).subscribe(data => { //doing stuff})
Is this close to what you are looking for?
It gets all of the posts, for each of the posts, it gets the user and all of the todos.
It first retrieves all of the posts. Then it pipes the retrieved
posts through a switchMap to flatten the result.
It uses forkJoin to combine the results for each post.
It uses forkJoin a second time to combine the associated user of the
post and their todos (which would be their likes in your scenario).
It then maps the result of the forkJoin into a structure consisting
of the post, the userName, and the list of todos for that user.
The template uses an async pipe to subscribe to the postData$
structure and access the desired piece of that structure.
NOTE: This won't be exactly the same for your code because I used a public user/post/todo API so I could ensure the following code worked.
// Get all posts
// Get the user of each post
// Get the todos for each user
postData$ = this.http.get<Post[]>(this.postUrl).pipe(
switchMap(posts =>
forkJoin(
posts.map(post =>
forkJoin([
this.http.get<User>(`${this.userUrl}/${post.userId}`),
this.http.get<ToDo[]>(`${this.todoUrl}?userId=${post.userId}`)
]).pipe(
map(([user, todos]) => ({
post: post,
userName: user.name,
todos: todos
}))
)
)
)
)
);
export interface Post {
userId: number;
id: number;
title: string;
body: string;
}
export interface ToDo {
userId: number;
id: number;
title: string;
completed: boolean;
}
export interface User {
id: number;
name: string;
username: string;
email: string;
website: string;
}
export interface PostData {
post: Post;
userName: string;
toDos: ToDo[];
}
I have a stackblitz here: https://stackblitz.com/edit/angular-todos-posts-forkjoin-deborahk

Mapping components to data with nesting

I am looking for a way to handle object data from the server, given data I'd like to pass all the data into a thing, and specify one thing and return that thing, for instance if I have a organization object and I wanted the createdAt date formatted. I would just be able to pass <data.Organization.createdAt {...organization}>. Is there anything that does this?
Here's the data
const contact = {
name: 'Thomas',
uuid: 1234
}
const orgnization = {
contact,
}
const scopedOrgniazation = {
orgnization
}
Here's the Components
import {RF, SalmonLink} from '../index'
const Contact = {
Name: ({ name }) => (name) ? <RF>{name}</RF> : <NA/>,
NameLink: ({ name, uuid }) => (uuid && name) ? <SalmonLink to={`/admin/organizations/${uuid}`}>{name}<SalmonLink> : <NA/>
}
const Organization = {
Contact
}
const ScopedOrganization = {
Organization
}
Desired Components API
I was thinking this may be possible by using something like lodash's flow or flowRight.
<Contact.Name {...contact}>
<Organization.Contact.Name {...organization}>
<ScopedOrganization.Organization.Contact.Name {...scopedOrgniazation}>

Removing an object from an array in Firestore

I'm just getting into Firebase, and really digging it so far, but I'm having a bit of an issue using a Cloud Function to remove an item from an array in a collection. In the app I'm using, users have a document in a users collection that contains user-specific data that doesn't fit within the authentication model. The data looks like this:
Screenshot of user collection structure.
(It's a fitness-related app, hence the array being called 'workouts')
The user has the ability to create a workout, and when they do, after it's created, a cloud function watching for new workouts adds the ID of the newly created workout to the user document, appending it to the workouts array using arrayUnion:
exports.addWorkoutToAuthorsListOfWorkouts = functions.firestore
.document('workouts/{workoutId}')
.onCreate((snap, context) => {
const id = context.params.workoutId
const name = snap.data().title
const uid = snap.data().author
const workout_reference = { id: id, name: name, uid: uid }
const workoutsRef = admin.firestore().collection("users").doc(uid)
return workoutsRef.update({
workouts: admin.firestore.FieldValue.arrayUnion(workout_reference)
})
})
This works fine, but I want the user to be able to delete workouts, and I didn't add a string to the workouts array, but instead an object like this:
{ id: "1214", name: "My workout", uid: "123asd" }
Now, for this exact use-case I could delete the array in my ReactJS app and then do an update, but I'm going to be adding the ability for users to "like" the workouts of other users, which will result in a reference to the workout being added to "workouts" in their personal user document. So if I, as a creator of a workout, delete my workout, I need to be able to delete it from the workouts array of any user who has it. Using arrayRemove didn't work because (I assume) I couldn't pass the object to be removed.
What's the best-practices way to do this? I made this attempt:
exports.removeWorkoutFromAuthorsListOfWorkouts = functions.firestore
.document('workouts/{workoutId}')
.onDelete((snap, context) => {
const id = context.params.workoutId
const uid = snap.data().author
const name = snap.data().name
let newWorkouts = new Array()
admin.firestore().collection("users").doc(uid).collection("workouts").get().then((querySnapshot) => {
querySnapshot.forEach((doc: any) => {
if (doc.id !== id) {
newWorkouts.push(doc.data())
}
});
});
const workoutsRef = admin.firestore().collection("users").doc(uid)
return workoutsRef.update({
workouts: newWorkouts
})
})
But Firebase didn't like it at all, and I'm new enough to the platform that I realize this is most likely due to the result of a knowledge gap, rather than any problem with Firestore or Cloud Functions.
Any help you could provide would be very much appreciated. Cheers!
UPDATE: Got it working, with the following code:
exports.removeWorkoutFromSubscribersListOfWorkouts = functions.firestore
.document('workouts/{workoutId}')
.onDelete((snap, context) => {
const workoutId = context.params.workoutId
const subscribers = snap.data().subscribers
let newWorkouts = new Array()
subscribers.forEach(subscriber => {
let userRef = admin.firestore().collection("users").doc(subscriber)
return userRef.get().then(doc => {
return userRef.update({
workouts: doc.data().workouts.filter(workout => workout.id !== workoutId)
})
})
})
.catch(() => {
console.log("error")
})
})

`updater` not working with Relay Modern because `ConnectionHandler.getConnection()` returns `undefined`

I'm using Relay Modern for my app and am trying to update the cache after a mutation using the updater and optimisticUpdater but it doesn't quite work.
Basically, I have a Link type with a votes connection - here's the relevant part of my schema:
type Link implements Node {
createdAt: DateTime!
description: String!
id: ID!
postedBy(filter: UserFilter): User
url: String!
votes(filter: VoteFilter, orderBy: VoteOrderBy, skip: Int, after: String, before: String, first: Int, last: Int): VoteConnection
}
type Vote implements Node {
createdAt: DateTime!
id: ID!
link(filter: LinkFilter): Link!
updatedAt: DateTime!
user(filter: UserFilter): User!
}
# A connection to a list of items.
type VoteConnection {
# Information to aid in pagination.
pageInfo: PageInfo
# A list of edges.
edges: [VoteEdge]
# Count of filtered result set without considering pagination arguments
count: Int!
}
# An edge in a connection.
type VoteEdge {
# The item at the end of the edge.
node: Vote
# A cursor for use in pagination.
cursor: String
}
Here's the code for my Link component request the votes in a fragment:
class Link extends Component {
render() {
const userId = localStorage.getItem(GC_USER_ID)
return (
<div>
{userId && <div onClick={() => this._voteForLink()}>▲</div>}
<div>{this.props.link.description} ({this.props.link.url})</div>
<div>{this.props.link.votes.edges.length} votes | by {this.props.link.postedBy ? this.props.link.postedBy.name : 'Unknown'} {this.props.link.createdAt}</div>
</div>
)
}
_voteForLink = () => {
const userId = localStorage.getItem(GC_USER_ID)
const linkId = this.props.link.id
CreateVoteMutation(userId, linkId, this.props.viewer.id)
}
}
export default createFragmentContainer(Link, graphql`
fragment Link_viewer on Viewer {
id
}
fragment Link_link on Link {
id
description
url
createdAt
postedBy {
id
name
}
votes(last: 1000, orderBy: createdAt_DESC) #connection(key: "Link_votes", filters: []) {
edges {
node {
id
user {
id
}
}
}
}
}
`)
Finally, this is the CreateVoteMutation with the updater:
const mutation = graphql`
mutation CreateVoteMutation($input: CreateVoteInput!) {
createVote(input: $input) {
vote {
id
link {
id
}
user {
id
}
}
}
}
`
export default (userId, linkId, viewerId) => {
const variables = {
input: {
userId,
linkId,
clientMutationId: ""
},
}
commitMutation(
environment,
{
mutation,
variables,
updater: (proxyStore) => {
const createVoteField = proxyStore.getRootField('createVote')
const newVote = createVoteField.getLinkedRecord('vote')
const viewerProxy = proxyStore.get(viewerId)
const connection = ConnectionHandler.getConnection(viewerProxy, 'Link_votes')
// `connection` is undefined, so the `newVote` doesn't get inserted
if (connection) {
ConnectionHandler.insertEdgeAfter(connection, newVote)
}
},
onError: err => console.error(err),
},
)
}
The call to ConnectionHandler.getConnection(viewerProxy, 'Link_votes') only returns undefined, so the newVote doesn't actually get inserted.
Does anyone see what I'm doing wrong?
Problem:
When you're getting your connection:
const connection = ConnectionHandler.getConnection(viewerProxy, 'Link_votes')
you're trying to get the connection 'Link_votes' on the ViewerProxy. However what you want to be doing is getting the connection on the link.
Solution:
First you would need to get the id of the link that your adding the vote to.
const linkId = newVote.getLinkedRecord('link').getValue('id');
Then you want to get the Link Proxy so that you can then get the correct connection.
const linkProxy = proxyStore.get(LinkId)
Now that you have the Link Proxy that represents the link that you wanted the connection for, you can now get that connection.
const connection = ConnectionHandler.getConnection(linkProxy, 'Link_votes')
Sweet so now you've got the connection. Which solves the issue you're having.
However there is another problem, the way you go on to add the vote is wrong first you need to create an Edge out of it, and then add the edge.
First we need to create an edge
const voteEdge = createEdge(proxyStore, connection, newVote, 'VoteEdge');
Now that we have the voteEdge we can append it to the connection.
ConnectionHandler.insertEdgeAfter(connection, voteEdge).
Now it should all work. However you probably shouldn't be using the updater function for this kind of action. You should be using the RANGE_ADD configuration https://facebook.github.io/relay/docs/mutations.html#range-add and change how your server responds to that mutation.

Resources