Manqo
Manqo
PPrisma
Created by Manqo on 10/9/2024 in #help-and-questions
I’m trying to fix an error I’m encountering in my Prisma code: This expression is not callable.
What im trying to accomplish is that when user creates an new record, we give it highest sortOrder. The error occurs in the findFirst function, and here's the message I’m seeing:
Find the first WorkExperience that matches the filter. Note, that providing undefined is treated as the value not being there. Read more here: https://pris.ly/d/null-undefined
Find the first WorkExperience that matches the filter. Note, that providing undefined is treated as the value not being there. Read more here: https://pris.ly/d/null-undefined
Additionally, I'm getting another error at the create function, which reads:
This expression is not callable.
Each member of the union type '(<T extends WorkExperienceCreateArgs<DefaultArgs>>(args: SelectSubset<T, WorkExperienceCreateArgs<DefaultArgs>>) => Prisma__WorkExperienceClient<...>) | ... 5 more ... |
This expression is not callable.
Each member of the union type '(<T extends WorkExperienceCreateArgs<DefaultArgs>>(args: SelectSubset<T, WorkExperienceCreateArgs<DefaultArgs>>) => Prisma__WorkExperienceClient<...>) | ... 5 more ... |
Here’s the relevant code:
type ModelMappingKeys =
| 'workexperiences'
| 'educations'
| 'languages'
| 'skills'
| 'references'
| 'certifications'
| 'licences';
export async function createExperience(
data: Partial<UnifiedFormType> & { formType: FormType; resumeId: string },
) {
const { formType, ...formData } = data;

const modelMapping = {
workexperiences: db.workExperience,
educations: db.education,
languages: db.language,
skills: db.skill,
references: db.reference,
certifications: db.certification,
licences: db.licence,
} as const;

function isValidFormType(type: FormType): type is ModelMappingKeys {
return type in modelMapping;
}

if (!isValidFormType(formType)) {
throw new Error(`Invalid form type: ${formType}`);
}

const model = modelMapping[formType];

const highestItem = await model.findFirst({
where: { resumeId: data.resumeId },
orderBy: { sortOrder: 'desc' },
});

const nextSortOrder = (highestItem?.sortOrder ?? -1) + 1;

const createdItem = await model.create({
data: {
...formData,
sortOrder: nextSortOrder,
},
});
revalidatePath(`/resume/${data.resumeId}`);
return createdItem;
}
type ModelMappingKeys =
| 'workexperiences'
| 'educations'
| 'languages'
| 'skills'
| 'references'
| 'certifications'
| 'licences';
export async function createExperience(
data: Partial<UnifiedFormType> & { formType: FormType; resumeId: string },
) {
const { formType, ...formData } = data;

const modelMapping = {
workexperiences: db.workExperience,
educations: db.education,
languages: db.language,
skills: db.skill,
references: db.reference,
certifications: db.certification,
licences: db.licence,
} as const;

function isValidFormType(type: FormType): type is ModelMappingKeys {
return type in modelMapping;
}

if (!isValidFormType(formType)) {
throw new Error(`Invalid form type: ${formType}`);
}

const model = modelMapping[formType];

const highestItem = await model.findFirst({
where: { resumeId: data.resumeId },
orderBy: { sortOrder: 'desc' },
});

const nextSortOrder = (highestItem?.sortOrder ?? -1) + 1;

const createdItem = await model.create({
data: {
...formData,
sortOrder: nextSortOrder,
},
});
revalidatePath(`/resume/${data.resumeId}`);
return createdItem;
}
3 replies
PPrisma
Created by Manqo on 9/25/2024 in #help-and-questions
Deleting User Account and All Related Data
I'm implementing a way for users to delete all their related data using Next.js 14 with App Router. This is my server action to handle data deletion after user confirmation:
'use server';
import { db } from '../lib/db';
import { S3Client, DeleteObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({
region: AWS_REGION,
credentials: {
accessKeyId: AWS_KEY,
secretAccessKey: AWS_SECRET,
},
});

export async function deleteUserAccount(userId: string) {
try {

const resumes = await db.resume.findMany({
where: { userId },
include: {
personalInfo: true,
},
});
for (const resume of resumes) {
if (resume.personalInfo?.imagePath) {
const imageName = resume.personalInfo.imagePath.split('/').pop();
if (imageName) {
await s3.send(
new DeleteObjectCommand({
Bucket: process.env.AWS_BUCKET_NAME,
Key: imageName,
}),
);
}
}
}

await db.$transaction([
db.personalInfo.deleteMany({ where: { resume: { userId } } }),
db.workExperience.deleteMany({ where: { resume: { userId } } }),
...
db.resume.deleteMany({ where: { userId } }),
db.coverletter.deleteMany({ where: { userId } }),
db.account.deleteMany({ where: { userId } }),
db.session.deleteMany({ where: { userId } }),
db.user.delete({ where: { id: userId } }),
]);
return { success: true };
} catch (error) {
return { success: false, error: 'Failed to delete account' };
}
}
'use server';
import { db } from '../lib/db';
import { S3Client, DeleteObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({
region: AWS_REGION,
credentials: {
accessKeyId: AWS_KEY,
secretAccessKey: AWS_SECRET,
},
});

export async function deleteUserAccount(userId: string) {
try {

const resumes = await db.resume.findMany({
where: { userId },
include: {
personalInfo: true,
},
});
for (const resume of resumes) {
if (resume.personalInfo?.imagePath) {
const imageName = resume.personalInfo.imagePath.split('/').pop();
if (imageName) {
await s3.send(
new DeleteObjectCommand({
Bucket: process.env.AWS_BUCKET_NAME,
Key: imageName,
}),
);
}
}
}

await db.$transaction([
db.personalInfo.deleteMany({ where: { resume: { userId } } }),
db.workExperience.deleteMany({ where: { resume: { userId } } }),
...
db.resume.deleteMany({ where: { userId } }),
db.coverletter.deleteMany({ where: { userId } }),
db.account.deleteMany({ where: { userId } }),
db.session.deleteMany({ where: { userId } }),
db.user.delete({ where: { id: userId } }),
]);
return { success: true };
} catch (error) {
return { success: false, error: 'Failed to delete account' };
}
}
This is the frontend function that gets called when confirm is clicked:
const handleDeleteAccount = async () => {
setIsDeleting(true);
const result = await deleteUserAccount(user.id);
setIsDeleting(false);
if (result.success) {
await signOut({ redirect: false });
router.push('/');
} else {
console.error(result.error);
}
};
const handleDeleteAccount = async () => {
setIsDeleting(true);
const result = await deleteUserAccount(user.id);
setIsDeleting(false);
if (result.success) {
await signOut({ redirect: false });
router.push('/');
} else {
console.error(result.error);
}
};
11 replies