I've got an odd error, I've been googling to no end and have been unable to figure this out.
I've got a prisma.schema looking like this;
// 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"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Account {
id String #id #default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? #db.Text
access_token String? #db.Text
expires_at Int?
token_type String?
scope String?
id_token String? #db.Text
session_state String?
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
##unique([provider, providerAccountId])
}
model Session {
id String #id #default(cuid())
sessionToken String #unique
userId String
expires DateTime
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String #id #default(cuid())
name String?
email String #unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
}
model VerificationToken {
identifier String
token String #unique
expires DateTime
##unique([identifier, token])
}
and a addUser.ts file looking like this...
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { User, PrismaClient } from '#prisma/client';
import type { NextApiRequest, NextApiResponse } from 'next';
type Data = {
name: string;
};
const prisma = new PrismaClient();
export default async(req: NextApiRequest, res: NextApiResponse) => {
const createUser: User = await prisma.user.create({
data:{
name: `${Math.random() * 10000}`,
email: `${Math.random() * 10000}#gmail.com`,
}
});
res.json('user created succesfully');
}
Trouble is when I run the code I get this error....
Error:
Invalid `prisma.user.create()` invocation:
{
data: {
name: '8096.003938770688',
email: '8343.394432092025#gmail.com'
~~~~~
}
}
Unknown arg `email` in data.email for type UserCreateInput. Did you mean `name`? Available args:
type UserCreateInput {
name: String
}
But if I look at the UserCreateInput type (I haven't made any changes to this file, I've used prisma generate to match my schema when I've made changes to it) I can see this....
export type UserCreateInput = {
id?: string
name?: string | null
email: string
emailVerified?: Date | string | null
image?: string | null
accounts?: AccountCreateNestedManyWithoutUserInput
sessions?: SessionCreateNestedManyWithoutUserInput
}
If I comment out the line email: ${Math.random() * 10000}#gmail.com, and set the schema to "email String? #unique" it works fine and creates the entry into the DB as expected, so it seems to be something with my email field but I can't figure out what.
I have been following multiple guides but none of them seem to expect this issue or have any resolutions for it.
I should point out, I am fairly new to development, and I'm not a developer by trade, so this is more of a learning thing for me :)
Appreciate your time guys
Related
I'm using Prisma w/ Postgres and am trying to have a simple 1-to-many relationship with a User which can have zero or more Product(s). I'm able to create 1 product for a particular user but when I try to create another product I'm met with this error: Invalid prisma.product.create() invocation: Unique constraint failed on the fields: ('userEmail'). I'm definitely missing something but probably need another pair of eyes on it.
schema.prisma
model Product {
id String #id #default(cuid())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String
description String?
published Boolean #default(false)
user User #relation(fields: [userEmail], references: [email])
userEmail String #unique
productImageUrl String?
}
model User {
id String #id #default(cuid())
name String?
email String? #unique
emailVerified DateTime?
image String?
active Boolean?
products Product[]
}
Next.js API route where I can POST to create new products for a user
const Index = async (_req: NextApiRequest, res: NextApiResponse) => {
const reqBody = _req.body ?? null;
if (!reqBody) res.status(200).json({ message: "No request body found" });
const product = await prisma.product.create({
data: {
user: {
connect: {
email: "xxx#x.com" // this user already exists in the DB
},
},
published: true,
name: "Test Product 3",
createdAt: new Date,
updatedAt: new Date,
}
})
res.status(200).json({ data: reqBody })
};
Silly mistake. All I needed to do was remove #unique from userEmail on the Product model.
you don't need to define foreign key userEmail in the product table as #uniuqe
I'm trying to query comments and the user who made the comments. I'm using Prisma to create the schema and Planetscale as a database.
Below you find part of my schema
model User {
id String #id #default(cuid())
name String?
email String? #unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
Comment Comment[]
}
model Comment {
id String #id #default(cuid())
text String
contentId String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
commenterId String?
commenter User? #relation(fields: [commenterId], references: [id])
}
This is my API route:
import type { NextApiRequest, NextApiResponse } from "next";
import prisma from "../../../lib/prisma";
export default async function handle(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "GET") {
return res.status(405).json({ msg: "Method not allowed" });
}
try {
const comments = await prisma.comment.findMany();
return res.status(200).json(comments);
} catch (err) {
console.error(err);
res.status(500).json({ msg: "Something went wrong." });
}
res.end();
}
The end goals is to query the comments and get an object with the commenter, so I can display name and image.
How should my #relation in the model Comment look like to make it possible to include the commenter in the query?
You need to tell prisma if you want to include a related model like this:
await prisma.comment.findmany({
include: {
commenter: true,
},
})
https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries
Having issue with inserting an employee and a user that have a relationship (only in the db ;))
The principle: A user can create multiple employees and then give them access by adding them as a user. An employee can have a user account. A user can be an employee.
Only one user account per employee. Also, by putting the password in a different table I hope to mitigate some accidental leaks where the password might be sent to the client, etc. [I still need to encrypt email and phone number in the db]
My Prisma model:
model User {
id String #id #default(dbgenerated("gen_random_uuid()")) #db.Uuid
username String #unique
password_hash Bytes
employee Employee? #relation("EmployeeUserInfo")
employeeId String #unique #db.Uuid
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
employeesAdded Employee[] #relation("EmployeeAddedByUser")
}
model Employee {
id String #id #default(dbgenerated("gen_random_uuid()")) #db.Uuid
first_name String
last_name String
phone_number String
user User? #relation("EmployeeUserInfo", fields: [userId], references: [id])
userId String #unique #db.Uuid
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
addedBy User? #relation("EmployeeAddedByUser", fields: [addedById], references: [id])
addedById String #db.Uuid
}
My Prisma client code:
// let user = await prisma.user.create({
// data: {
// username: 'system',
// password_hash: Buffer.from(hash),
// employee: {
// create: {
// first_name: 'system',
// last_name: 'system',
// phone_number: '5555555555'
// }
// },
// },
// });
let user = await prisma.employee.create({
data: {
first_name: 'system',
last_name: 'system',
phone_number: '5555555555',
user: {
create: {
username: 'system',
password_hash: Buffer.from(hash),
}
},
},
select: {
user: true
}
});
The error I receive is:
Invalid `prisma.employee.create()` invocation:
{
data: {
first_name: 'system',
last_name: 'system',
phone_number: '5555555555',
user: {
create: {
username: 'system',
password_hash: Buffer(3),
+ employeeId: String,
? id?: String,
? createdAt?: DateTime,
? updatedAt?: DateTime,
? employeesAdded?: {
? create?: EmployeeCreateWithoutAddedByInput | EmployeeCreateWithoutAddedByInput | EmployeeUncheckedCreateWithoutAddedByInput | EmployeeUncheckedCreateWithoutAddedByInput,
? connectOrCreate?: EmployeeCreateOrConnectWithoutAddedByInput | EmployeeCreateOrConnectWithoutAddedByInput,
? createMany?: EmployeeCreateManyAddedByInputEnvelope,
? connect?: EmployeeWhereUniqueInput | EmployeeWhereUniqueInput
? }
}
}
},
select: {
user: true
}
}
Argument employeeId for data.user.create.employeeId is missing.
Note: Lines with + are required, lines with ? are optional.
I tried in both directions: User creates employee and Employee creates user.
With the commented code, I get a similar message Argument employeeId for data.employeeId is missing..
I guess I can't make this work because they both reference each other (even if they are optional)? If so, what would make the most sense from a security/db perspective? I saw a suggestion about using select to return the id but unless I'm not using it the right way, it doesn't work.
Using Nexus-Prisma in the background, in case that helps.
I encountered a problem while trying to seed the user table.
I have a one-to-one relationship between the User and UserSettings model in it.
async function generateUsers() {
const users = [];
for (let i = 0; i < randomUsersCount; i++) {
users[i] = {
first_name: faker.name.firstName(),
last_name: faker.name.lastName(),
email: faker.internet.email(),
password: await hashPassword('testtest'),
phone: faker.phone.phoneNumber('###-###-###'),
role: 'USER',
is_blocked: false,
user_settings : {
create: {
language: 'PL',
color: faker.internet.color(),
}
}
};
}
await prisma.user.createMany({
data: users,
});
}
Error message:
Unknown arg `user_settings` in data.0.user_settings for type UserCreateManyInput. Available args:
type UserCreateManyInput {
id?: Int
first_name: String
last_name: String
email: String
phone: String
password: String
role: UserRoles
is_blocked?: Boolean
created_at?: DateTime
updated_at?: DateTime
}
but in my model the field exists:
model User {
id Int #id #default(autoincrement())
first_name String
last_name String
email String #unique
phone String
password String
role UserRoles
is_blocked Boolean #default(false)
created_at DateTime #default(now())
updated_at DateTime #updatedAt
user_settings UserSettings?
}
model UserSettings {
id Int #id #default(autoincrement())
language Languages
color String
user_id Int
user User #relation(fields: [user_id], references: [id])
}
When I turn on Prisma Studio, I can see the column present in the table.
Where did I go wrong?
I have run npx prisma generate and npx prisma migrate and even npx prisma migrate reset many times, without success.
You are trying to use nest createMany which isn't supported.
This is from the documentation:
You cannot create or connect relations - you cannot nest create,
createMany, connect, connectOrCreate inside a top-level createMany
As an alternative I would suggest to create users inside the loop while you are creating data.
async function generateUsers() {
const users = [];
for (let i = 0; i < randomUsersCount; i++) {
users[i] = {
first_name: faker.name.firstName(),
last_name: faker.name.lastName(),
email: faker.internet.email(),
password: await hashPassword('testtest'),
phone: faker.phone.phoneNumber('###-###-###'),
role: 'USER',
is_blocked: false,
user_settings : {
create: {
language: 'PL',
color: faker.internet.color(),
}
}
};
await prisma.user.create({
data: users[i],
});
}
}
I'm encountering some interesting behaviour when using Prisma ORM. It is related to Prisma's generated types, and I've been skimming the docs trying to find out more, but there doesn't seem to be much info about generated types in there (please correct me if I'm mistaken). Here's the behaviour:
Say I have a model with two 1-1 relations (Profile in the example below):
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int #id #default(autoincrement())
name String
profile Profile?
}
model Profile {
id Int #id #default(autoincrement())
name String
userId Int?
user User? #relation(fields: [userId], references: [id])
photoId Int?
photo Photo? #relation(fields: [photoId], references: [id])
}
model Photo {
id Int #id #default(autoincrement())
url String
profile Profile?
}
The following code works when creating a new profile:
const user = await prisma.user.create({ data: { name: "TestUser" } });
const profile = await prisma.profile.create({
data: {
name: "TestProfile",
user: { connect: { id: user.id } },
photo: { create: { url: "http://example.com/img" } },
},
});
... but this fails with an error:
const user = await prisma.user.create({ data: { name: "TestUser" } });
const profile = await prisma.profile.create({
data: {
name: "TestProfile",
userId: user.id,
photo: { create: { url: "http://example.com/img" } },
},
});
The error is:
Unknown arg userId in data.userId for type ProfileCreateInput. Did you mean user? Available args:
type ProfileCreateInput {
name: String
user?: UserCreateNestedOneWithoutProfileInput
photo?: PhotoCreateNestedOneWithoutProfileInput
}
Why is the second create-profile code invalid?
Prisma essentially generates two type definitions for a create query. This is implemented with a XOR type, which ensures that only one definition out of two is fully specified and passed to the query:
export type ProfileCreateArgs = {
/* ... */
data: XOR<ProfileCreateInput, ProfileUncheckedCreateInput>;
}
The definitions are called checked and unchecked, the former using nested fields and the latter using raw ids:
export type ProfileCreateInput = {
id?: number;
/* ... */
user?: UserCreateNestedOneWithoutProfileInput;
photo?: PhotoCreateNestedOneWithoutProfileInput;
}
export type ProfileUncheckedCreateInput = {
id?: number;
/* ... */
userId?: number;
photoId?: number;
}
Which basically means that you either provide all references as connect, create etc. relations (checked) or as raw ids (unchecked). You cannot mix the styles, this is not supported.