How to solve circular dependency. I have two files one is conversation.serialization.ts
#Exclude()
export class ConversationSerialization {
#ApiResponseProperty({ type: () => [MessageSerialization] })
#Expose({
groups: [CONVERSATION.FIND_MY, CONVERSATION.FIND_BY_ID],
})
#Type(() => MessageSerialization)
messages: MessageSerialization[];
constructor(partial: Partial<ConversationSerialization>) {
Object.assign(this, partial);
}
}
and second is message.serialization.ts
#Exclude()
export class MessageSerialization {
#Type(() => ConversationSerialization)
#ApiResponseProperty()
#Expose({ groups: [] })
conversation?: ConversationSerialization;
constructor(partial: Partial<MessageSerialization>) {
Object.assign(this, partial);
}
}
Both classes depends on each other and causes circular dependency. I tried to use barrel export for this, but it didn't help a lot. Barrel exports just fix circular dependency in typescript files but in compiled js is still remained. Here is my tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false
}
}
schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
relationMode = "prisma"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String #id #default(cuid())
email String #unique #db.VarChar(255)
name String #db.VarChar(255)
password String #unique #db.VarChar(255)
resetPasswordToken String? #db.VarChar(255)
resetPasswordTokenExpiresAt DateTime?
sentMessages Messages[] #relation("SentMessages")
seenMessages SeenMessages[]
sentFriendRequests FriendsRequest[] #relation("FriendsRequestSender")
receivedFriendRequests FriendsRequest[] #relation("FriendsRequesReceiver")
myFriends Friends[] #relation("UserFriends")
friendsBy Friends[] #relation("UserFriendsBy")
groupsOwned Groups[]
ConversationsOnUsers ConversationsOnUsers[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
model Friends {
user User #relation("UserFriends", fields: [userId], references: [id])
userId String
friend User #relation("UserFriendsBy", fields: [friendId], references: [id])
friendId String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##id([userId, friendId])
}
model Messages {
id String #id #default(cuid())
message String #db.VarChar(500)
seenBy SeenMessages[]
sender User #relation(name: "SentMessages", fields: [senderId], references: [id])
senderId String
conversation Conversations #relation(fields: [conversationsId], references: [id])
conversationsId String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##index([senderId, conversationsId])
}
model SeenMessages {
seenBy User #relation(fields: [seenById], references: [id])
seenById String
message Messages #relation(fields: [messageId], references: [id])
messageId String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##id([seenById, messageId])
}
model Conversations {
id String #id #default(cuid())
isGroup Boolean? #default(false)
messages Messages[]
group Groups?
conversationsOnUsers ConversationsOnUsers[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
model ConversationsOnUsers {
user User #relation(fields: [userId], references: [id])
userId String
conversation Conversations #relation(fields: [conversationsId], references: [id])
conversationsId String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##id([userId, conversationsId])
}
model FriendsRequest {
sender User #relation(name: "FriendsRequestSender", fields: [senderId], references: [id])
senderId String
receiver User #relation(name: "FriendsRequesReceiver", fields: [receiverId], references: [id])
receiverId String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##id([senderId, receiverId])
}
model Groups {
name String #db.VarChar(255)
isPublic Boolean? #default(false)
owner User #relation(fields: [ownerId], references: [id])
ownerId String
conversation Conversations #relation(fields: [conversationsId], references: [id])
conversationsId String #unique
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##id([ownerId, conversationsId])
}
Related
I have a model called "Setup"
model Setup {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #unique #db.ObjectId
user User? #relation(fields: [userId], references: [id])
contract String[]
legal String[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
In this model i want to store an array like
const contractData = {
id: '729a4839f3dapob44zt2b4b1',
name: 'Example Name',
text: 'Example Text'
}
so in my above model "Setup" i want to store the contractData
prisma.setup.create({
data: {
userId: '6399bc74426f71f2da6e316c',
personal: [],
contract: contractData,
legal: []
}
})
Unfortunately, this not work.
How can i define an Object for contract and store this in my database?
If you want to store a raw JSON, check out this guide: https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields
You will want to use the Json in Prisma in order to be able to store a raw JSON object (or multiple JSON objects as an array.)
model Setup {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #unique #db.ObjectId
user User? #relation(fields: [userId], references: [id])
contract Json[]
legal String[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
Your Prisma prisma.setup.create query would basically be the exact same. Note that querying for what's in this JSON will be trickier - I would recommend creating a new model and then connecting it to the Setup model, but that if that isn't an option you can still perform some limited queries on the contract field.
Docs: https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filter-on-a-json-field
In order to store an object in the contract field, you will need to change the type of the contract field from String[] to Object[].
model Setup {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #unique #db.ObjectId
user User? #relation(fields: [userId], references: [id])
contract Object[]
legal String[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
store an object in the contract field like
prisma.setup.create({
data: {
userId: '6399bc74426f71f2da6e316c',
personal: [],
contract: [contractData],
legal: []
}
})
contract field is now an array, so you will need to pass the object as an element of the array, like [contractData]
I my schema.prisma file I have those 2 models:
model User {
id String #id #default(uuid()) #db.Uuid
firstName String #map("first_name") #db.VarChar(40)
lastName String #map("last_name") #db.VarChar(40)
email String #unique #db.Citext
phone String #db.VarChar(60)
dialCode String #map("dial_code") #db.VarChar(5)
password String #db.VarChar(500)
twoFactorSecret String #db.VarChar(300)
roleId String #map("role_id") #db.Uuid
role Role #relation(fields: [roleId], references: [id])
customPermissions UserCustomPermission[]
updatedAt DateTime #default(now()) #updatedAt #map("updated_at") #db.Timestamptz(6)
createdAt DateTime #default(now()) #map("created_at") #db.Timestamptz(6)
##unique([dialCode, phone], map: "phone_number_unique")
##map("user")
UserAction UserAction[]
}
model UserAction {
id String #id #default(uuid()) #db.Uuid
userId String #map("user_id") #db.Uuid
method String #db.VarChar(120)
url String #db.VarChar(120)
userAgent String #db.VarChar(120)
requestBody Json?
responseBody Json?
user User #relation(fields: [userId], references: [id])
updatedAt DateTime #default(now()) #updatedAt #map("updated_at") #db.Timestamptz(6)
createdAt DateTime #default(now()) #map("created_at") #db.Timestamptz(6)
}
It is supposed to be one-to-many connection, but I have this warning in terminal when trigger function that creates record:
async createRecord({userId, method, url, userAgent, requestBody, responseBody}) {
return this.prisma.userAction.create({
data: {userId, method, url, userAgent, requestBody, responseBody}
})
}
And this warning:
+ user: {
+ create?: UserCreateWithoutUserActionInput | UserUncheckedCreateWithoutUserActionInput,
+ connectOrCreate?: UserCreateOrConnectWithoutUserActionInput,
+ connect?: UserWhereUniqueInput
+ },
? id?: String,
? updatedAt?: DateTime,
? createdAt?: DateTime
}
}
Argument user for data.user is missing.
Note: Lines with + are required, lines with ? are optional.
Actually, everything seems to be working fine, but I am wondering on how to fix this. I guess, that connection between 2 tables was created incorrect, but I have never worked with prisma before, so I don't really know where error is.
So, how can I fix this? Thanks in advance!
I faced this error because I passed an undefined value to a foreign key field of one of my models.
In your case, should be checked that createRecord is being invoked with a valid userId.
I would like to show the "Most used Hashtags” in my app.
It's just a simple many-to-many relation:
model Post {
id Int #id #default(autoincrement())
title String #db.VarChar(255)
description String #db.VarChar(255)
hashtags PostHashtag[]
}
model PostHashtag {
post Post #relation(fields: [postId], references: [id])
postId Int
hashtag Hashtag #relation(fields: [hashtagId], references: [id])
hashtagId Int
##id([postId, hashtagId])
##unique([postId, hashtagId])
}
model Hashtag {
id Int #id #default(autoincrement())
name String #db.VarChar(24)
posts PostHashtag[]
}
I cannot really find a way to groupBy the "name" field of the "Hashtag" in the PostHashtag table.
My goal is a query which returns me the top 15 used hashtags.
And unfortunately the docs won't help me with this.
This will return the top 15 used hashtags by ordering with posts counts, with the counts included in the result:
const topHashtags = await prisma.hashtag.findMany({
take: 15,
orderBy: {
posts: { _count: 'desc' },
},
include: {
_count: {
select: { posts: true },
},
},
});
Was easier than I thought:
return await prisma.hashtag.groupBy({
by: ['name'],
_count:{
name: true
},
orderBy: {
_count: {
name: 'desc',
}
}
})
I´m doing an Spotify clone and I´m trying to add a song to a playlist but my query doesn't work, until this point, everything was good following the documentation on prisma docs, but I cannot do this query, every time get an error, so if someone can tell me, how can I do this with an example, I'll be very grateful.
My question is, having this schema, how can I add a song to a playlist? there are two models affected by the query, song (where i am trying to add) and playlist.
My schema:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
model User {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
email String #unique
firstName String
lastName String
password String
playlists Playlist[]
}
// here
model Song {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String
artist Artist #relation(fields: [artistId], references: [id])
artistId Int
playlists Playlist[]
duration Int
url String
}
model Artist {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
songs Song[]
name String #unique
}
// here
model Playlist {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String
songs Song[]
user User #relation(fields: [userId], references: [id])
userId Int
}
I am trying to add the song like this:
let songId = 1;
let playlistId = 1;
let lists;
// get the playlists the song is part of
lists = await prisma.song.findFirst({
select: {
playlists: true
},
where: {
id: +songId
}
})
// get the playlist data i need
const list = await prisma.playlist.findUnique({
where: {
id: playlistId
}
})
// create the array for update with the data
// plus the data I want to add
lists = [ ...lists.playlists, list ]
// trying to update the old array with the new data (lists)
// this is what i'm doing wrong, help please
await prisma.song.update({
where: { id: +songId },
data:{
playlists: lists
}
})
after many tries i finally got what i want if anyone knows a better way please tell me, i want to learn, for now this is my solution:
i need to send each value as id: playlistId
const song = await prisma.song.findUnique({
select: {
playlists: true
},
where: {
id: +songId
}
})
// get an array of objects, id: playlistId
const songPlaylistsIds = song.playlists.map( playlist => ({id: playlist.id}))
// I prepare the array with the content that already exists plus the new content that I want to add:
const playlists = [...songPlaylistsIds, { id: playlistId}]
await prisma.song.update({
where: { id: +songId },
data:{
playlists: {
// finally for each object in the array i get, id: playlistId and it works.
set: playlists.map( playlistSong => ({ ...playlistSong }))
}
}
})
Problems I had doing this: I was wrong in thinking that it should work as simple as playlist: lists I wanted to change the content to a new one but I couldn't, I needed to send the values one by one.
Another error when I get the content of the playlists. I had the full object but just needed to send the id.
And lastly, in the prisma documentation, there is a method like set, push, but this method doesn't work, at least I don't know how to make push work
I am creating a basic crud api with nodejs and prisma. My Schema is as follows:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
model Category {
id String #unique #default(cuid())
title String
description String
products Product[]
}
model Product {
id String #unique #default(cuid())
title String
description String
price Float
createdAt DateTime #default(now())
updatedAt DateTime?
category Category? #relation(fields: [categoryId], references: [id])
categoryId String?
}
I am trying to make the products field in the Category model optional. But Prisma doesn't allow that. But I want my users to create a category even without creating a post or vice-versa. How can I get around this?
According to the Prisma documentation, lists cannot be optional: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#remarks-5
However, the products field not being optional does not mean that it cannot be an empty when a new Category is created:
await prisma.category.create({
data: {
title: 'books',
description: 'books',
products: {},
}
})
Then you can create or connect the product later:
await prisma.category.update({
where: {
id: "category-id"
},
data: {
products: {
connect: {
id: "product-id"
}
}
}
})