prismock
prismock copied to clipboard
Client Extensions
This is more of a question. I use client extensions (https://www.prisma.io/docs/concepts/components/prisma-client/client-extensions) pretty heavily in my code. I can mock and recreate those on my own but does Prismock support them?
Hello @ajhollowayvrm , there is actually a dummy implementation of the $extends
method in prismock
, but it won't be enough if you are really using it...
I'll have a look to get a better support for $extends
in the next few days/weeks. If you have a public repo with specific use-cases, let me know, I'll use it to validate my configuration.
export const DBConn = new PrismaClient({
log: [
{
emit: 'stdout',
level: 'error',
},
{
emit: 'stdout',
level: 'info',
},
{
emit: 'stdout',
level: 'warn',
},
],
})
.$extends({ name: 'TypeConversion Extensions', query: ClientExtensions })
.$extends({
name: 'User Attributes',
result: {
users: {
injectUserAttributes: {
name: 'inject user attributes function',
needs: { id: true },
compute(user: any) {
return async (requestingUserCompanyID?: number) => {
// Determines if user_attributes are needed based on fields being returned
if (Object.keys(user).some((column) => UserAttributesFields.includes(column))) {
if (!user.hasOwnProperty('user_attributes')) {
user.user_attributes = await DBConn.user_attributes.findMany({
where: { user_id: user.id },
});
}
await injectUserAttributes(user, requestingUserCompanyID);
}
return user;
};
},
},
updateAttributes: {
name: 'update user attributes function',
needs: { id: true, companyid: true, recognition_manager: true, recognition_admin: true, custom_manager_budget: true },
compute(data) {
return () =>
DBConn.user_attributes.update({
where: { user_id_company_id: { user_id: data.id, company_id: data.companyid } },
data: {
manager: data.recognition_manager,
admin: data.recognition_admin,
budget: data.custom_manager_budget,
},
include: {
users: true,
},
});
},
},
key: {
name: 'manger key',
needs: { first_name: true, last_name: true, username: true },
// used for manager in manager.controller.ts
compute(data) {
return data.first_name + ' ' + data.last_name + ' ' + data.username;
},
},
},
},
})
.$extends({
model: {
users: {
async exists(where) {
const count = await DBConn.users.count({ where });
return count > 0;
},
},
},
});
@morintd here's an example of how I use it
Thanks @ajhollowayvrm , I've been experimenting with extensions in the past few days. I don't see it getting complete support short-term, but I'll add functionalities incrementally.
I might use your example and report back about it here.
Hey @morintd. First of all: Thanks for this awesome library!
I am also using extensions for my prisma client. My use case is to add a field __caslSubjectType__
, that adds the models name to each object coming from prisma. I need that for the authorization library casl (v6) so it can detect the corresponding model of the object:
import { Prisma, PrismaClient } from "@prisma/client";
const brandExtension = Prisma.defineExtension((client) => {
type ModelKey = Exclude<keyof typeof client, `$${string}` | symbol>;
type Result = {
[K in ModelKey]: {
__caslSubjectType__: { needs: object; compute: () => K };
};
};
const result = {} as Result;
const modelKeys = Object.keys(client).filter(
(key) => !key.startsWith("$"),
) as ModelKey[];
modelKeys.forEach((k) => {
const capK = k.charAt(0).toUpperCase() + k.slice(1);
result[k] = {
__caslSubjectType__: { needs: {}, compute: () => capK as any },
};
});
return client.$extends({ result });
});
export const prisma = new PrismaClient().$extends(brandExtension);
So if the prisma model is named User
, each user has a field __caslSubjectType__: "User"
.
Can you think of any other good solution I could achieve the same with, without using extensions with prismock? Or even better: Get that extension to work with it? That would be great!